From 8d90cfadf0d9a602e5e9e92a73b459cf354e8249 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 21 Dec 2020 14:34:01 +0800 Subject: [PATCH] Update nuvoton porting. 1. Make up sources and bugfix. 2. Add nu_gpio_pin_get. 3. Add PM operator in USB host driver. 4. Support NUC980 stage 1 and add nk-980iot board. --- bsp/nuvoton/README.md | 5 +- .../libraries/m480/StdDriver/src/nu_can.c | 4 +- .../libraries/m480/USBHostLib/inc/usbh_lib.h | 2 +- .../libraries/m480/USBHostLib/src/usb_core.c | 2 +- bsp/nuvoton/libraries/m480/rtt_port/Kconfig | 7 + .../m480/rtt_port/drv_bpwm_capture.c | 6 +- bsp/nuvoton/libraries/m480/rtt_port/drv_can.c | 9 +- bsp/nuvoton/libraries/m480/rtt_port/drv_clk.c | 60 +- bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c | 23 +- bsp/nuvoton/libraries/m480/rtt_port/drv_crc.h | 1 - .../libraries/m480/rtt_port/drv_crypto.c | 299 +- .../libraries/m480/rtt_port/drv_ecap.c | 9 +- .../m480/rtt_port/drv_epwm_capture.c | 15 +- bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c | 7 +- .../libraries/m480/rtt_port/drv_gpio.c | 29 +- bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c | 6 +- .../libraries/m480/rtt_port/drv_pdma.c | 109 +- .../libraries/m480/rtt_port/drv_pdma.h | 1 + bsp/nuvoton/libraries/m480/rtt_port/drv_rtc.c | 10 +- bsp/nuvoton/libraries/m480/rtt_port/drv_spi.c | 35 +- .../m480/rtt_port/drv_timer_capture.c | 24 +- .../libraries/m480/rtt_port/drv_trng.c | 2 +- .../libraries/m480/rtt_port/drv_trng.h | 1 - .../libraries/m480/rtt_port/drv_uart.c | 4 +- .../libraries/m480/rtt_port/drv_usbd.c | 2 +- .../libraries/m480/rtt_port/drv_usbhost.c | 104 +- .../libraries/m480/rtt_port/drv_uspi.c | 2 +- bsp/nuvoton/libraries/m480/rtt_port/drv_wdt.c | 23 +- .../libraries/nu_packages/Demo/SConscript | 1 + .../nu_packages/Demo/usbd_hid_dance_mouse.c | 27 +- .../nu_packages/ILI9341/ili9341_ebi.c | 9 + .../nu_packages/ILI9341/ili9341_spi.c | 10 +- .../nu_packages/ILI9341/lcd_ili9341.c | 62 +- .../nu_packages/ILI9341/lcd_ili9341.h | 10 +- bsp/nuvoton/libraries/nu_packages/Kconfig | 8 + .../nu_packages/NuUtils/inc/nu_bitutil.h | 6 +- .../libraries/nuc980/Driver/Include/NuMicro.h | 47 + .../nuc980/Driver/Include/emac_reg.h | 2063 +++++++++++++ .../libraries/nuc980/Driver/Include/nu_adc.h | 110 + .../libraries/nuc980/Driver/Include/nu_can.h | 461 +++ .../libraries/nuc980/Driver/Include/nu_cap.h | 471 +++ .../nuc980/Driver/Include/nu_crypto.h | 1456 +++++++++ .../libraries/nuc980/Driver/Include/nu_ebi.h | 418 +++ .../libraries/nuc980/Driver/Include/nu_emac.h | 396 +++ .../nuc980/Driver/Include/nu_etimer.h | 869 ++++++ .../libraries/nuc980/Driver/Include/nu_gpio.h | 835 ++++++ .../libraries/nuc980/Driver/Include/nu_i2c.h | 541 ++++ .../libraries/nuc980/Driver/Include/nu_i2s.h | 132 + .../libraries/nuc980/Driver/Include/nu_pdma.h | 1249 ++++++++ .../libraries/nuc980/Driver/Include/nu_pwm.h | 271 ++ .../libraries/nuc980/Driver/Include/nu_qspi.h | 929 ++++++ .../libraries/nuc980/Driver/Include/nu_rtc.h | 445 +++ .../libraries/nuc980/Driver/Include/nu_sc.h | 425 +++ .../nuc980/Driver/Include/nu_scuart.h | 333 ++ .../libraries/nuc980/Driver/Include/nu_sdh.h | 721 +++++ .../libraries/nuc980/Driver/Include/nu_spi.h | 852 ++++++ .../libraries/nuc980/Driver/Include/nu_sys.h | 838 ++++++ .../libraries/nuc980/Driver/Include/nu_uart.h | 888 ++++++ .../libraries/nuc980/Driver/Include/nu_usbd.h | 942 ++++++ .../libraries/nuc980/Driver/Include/nu_wdt.h | 218 ++ .../libraries/nuc980/Driver/Include/nu_wwdt.h | 118 + .../libraries/nuc980/Driver/Include/nuc980.h | 1735 +++++++++++ .../Driver/Library/libStdDriver.uvprojx | 495 +++ .../Driver/Library/libStdDriver_4.uvproj | 501 ++++ .../libraries/nuc980/Driver/SConscript | 26 + .../libraries/nuc980/Driver/Source/nu_can.c | 1286 ++++++++ .../libraries/nuc980/Driver/Source/nu_cap.c | 397 +++ .../nuc980/Driver/Source/nu_crypto.c | 2671 +++++++++++++++++ .../libraries/nuc980/Driver/Source/nu_ebi.c | 190 ++ .../libraries/nuc980/Driver/Source/nu_emac.c | 1158 +++++++ .../nuc980/Driver/Source/nu_etimer.c | 490 +++ .../libraries/nuc980/Driver/Source/nu_gpio.c | 151 + .../libraries/nuc980/Driver/Source/nu_i2c.c | 1243 ++++++++ .../libraries/nuc980/Driver/Source/nu_i2s.c | 466 +++ .../libraries/nuc980/Driver/Source/nu_pdma.c | 443 +++ .../libraries/nuc980/Driver/Source/nu_qspi.c | 598 ++++ .../libraries/nuc980/Driver/Source/nu_rtc.c | 808 +++++ .../nuc980/Driver/Source/nu_scuart.c | 242 ++ .../libraries/nuc980/Driver/Source/nu_sdh.c | 1181 ++++++++ .../libraries/nuc980/Driver/Source/nu_spi.c | 603 ++++ .../libraries/nuc980/Driver/Source/nu_sys.c | 723 +++++ .../libraries/nuc980/Driver/Source/nu_uart.c | 776 +++++ .../libraries/nuc980/Driver/Source/nu_usbd.c | 679 +++++ .../libraries/nuc980/Driver/Source/nu_wdt.c | 67 + .../libraries/nuc980/Driver/Source/nu_wwdt.c | 67 + bsp/nuvoton/libraries/nuc980/README.md | 28 + bsp/nuvoton/libraries/nuc980/SConscript | 15 + .../libraries/nuc980/Script/NUC980xx41.ini | 24 + .../libraries/nuc980/Script/NUC980xx61.ini | 24 + .../libraries/nuc980/Script/NUC980xx71.ini | 26 + bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig | 656 ++++ .../libraries/nuc980/rtt_port/SConscript | 35 + .../libraries/nuc980/rtt_port/drv_adc.c | 286 ++ .../libraries/nuc980/rtt_port/drv_can.c | 554 ++++ .../libraries/nuc980/rtt_port/drv_common.c | 81 + .../libraries/nuc980/rtt_port/drv_common.h | 20 + .../libraries/nuc980/rtt_port/drv_crypto.c | 764 +++++ .../libraries/nuc980/rtt_port/drv_ebi.c | 44 + .../libraries/nuc980/rtt_port/drv_ebi.h | 53 + .../libraries/nuc980/rtt_port/drv_emac.c | 637 ++++ .../libraries/nuc980/rtt_port/drv_etimer.c | 297 ++ .../libraries/nuc980/rtt_port/drv_gpio.c | 344 +++ .../libraries/nuc980/rtt_port/drv_gpio.h | 33 + .../libraries/nuc980/rtt_port/drv_i2c.c | 394 +++ .../libraries/nuc980/rtt_port/drv_i2c.h | 36 + .../libraries/nuc980/rtt_port/drv_i2s.c | 590 ++++ .../libraries/nuc980/rtt_port/drv_i2s.h | 96 + .../libraries/nuc980/rtt_port/drv_pdma.c | 1131 +++++++ .../libraries/nuc980/rtt_port/drv_pdma.h | 91 + .../libraries/nuc980/rtt_port/drv_pwm.c | 342 +++ .../libraries/nuc980/rtt_port/drv_qspi.c | 400 +++ .../libraries/nuc980/rtt_port/drv_qspi.h | 20 + .../libraries/nuc980/rtt_port/drv_rtc.c | 348 +++ .../libraries/nuc980/rtt_port/drv_scuart.c | 336 +++ .../libraries/nuc980/rtt_port/drv_sdh.c | 646 ++++ .../libraries/nuc980/rtt_port/drv_softi2c.c | 229 ++ .../libraries/nuc980/rtt_port/drv_spi.c | 639 ++++ .../libraries/nuc980/rtt_port/drv_spi.h | 53 + .../libraries/nuc980/rtt_port/drv_sys.c | 315 ++ .../libraries/nuc980/rtt_port/drv_sys.h | 259 ++ .../libraries/nuc980/rtt_port/drv_systick.c | 86 + .../libraries/nuc980/rtt_port/drv_uart.c | 864 ++++++ .../libraries/nuc980/rtt_port/drv_uart.h | 20 + .../libraries/nuc980/rtt_port/drv_wdt.c | 411 +++ bsp/nuvoton/nk-980iot/.config | 817 +++++ bsp/nuvoton/nk-980iot/Kconfig | 29 + bsp/nuvoton/nk-980iot/README.md | 102 + bsp/nuvoton/nk-980iot/SConscript | 14 + bsp/nuvoton/nk-980iot/SConstruct | 55 + bsp/nuvoton/nk-980iot/applications/SConscript | 11 + bsp/nuvoton/nk-980iot/applications/main.c | 84 + bsp/nuvoton/nk-980iot/applications/mnt.c | 190 ++ bsp/nuvoton/nk-980iot/board/Kconfig | 133 + bsp/nuvoton/nk-980iot/board/SConscript | 14 + bsp/nuvoton/nk-980iot/board/board.h | 37 + bsp/nuvoton/nk-980iot/board/board_dev.c | 218 ++ bsp/nuvoton/nk-980iot/board/fal_cfg.h | 46 + bsp/nuvoton/nk-980iot/board/nu_pin_init.c | 97 + .../nk-980iot/linking_scripts/nuc980.ld | 114 + .../nk-980iot/linking_scripts/nuc980.sct | 11 + bsp/nuvoton/nk-980iot/rtconfig.py | 88 + bsp/nuvoton/nk-980iot/template.uvproj | 394 +++ bsp/nuvoton/nk-980iot/template.uvprojx | 387 +++ bsp/nuvoton/numaker-iot-m487/.config | 2 +- .../numaker-iot-m487/Nu_Link_Driver.ini | 19 +- bsp/nuvoton/numaker-iot-m487/README.md | 6 +- .../numaker-iot-m487/applications/mnt.c | 10 - bsp/nuvoton/numaker-iot-m487/board/board.c | 19 +- bsp/nuvoton/numaker-iot-m487/board/board.h | 16 +- .../linking_scripts/m480_flash.icf | 4 +- .../linking_scripts/m480_link.ld | 10 +- bsp/nuvoton/numaker-pfm-m487/.config | 2 +- bsp/nuvoton/numaker-pfm-m487/README.md | 6 +- .../numaker-pfm-m487/applications/mnt.c | 9 - bsp/nuvoton/numaker-pfm-m487/board/board.c | 19 +- bsp/nuvoton/numaker-pfm-m487/board/board.h | 16 +- .../linking_scripts/m480_flash.icf | 4 +- .../linking_scripts/m480_link.ld | 10 +- 158 files changed, 47822 insertions(+), 356 deletions(-) create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/emac_reg.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_can.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_cap.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_crypto.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_ebi.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_emac.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_etimer.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_gpio.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2c.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2s.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pdma.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_qspi.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_rtc.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sc.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_scuart.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sdh.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_spi.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sys.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_uart.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_usbd.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_wdt.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nu_wwdt.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Include/nuc980.h create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver.uvprojx create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver_4.uvproj create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/SConscript create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_can.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_cap.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_ebi.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_etimer.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_gpio.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2c.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2s.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_pdma.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_qspi.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_rtc.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_scuart.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sdh.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_spi.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sys.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_uart.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_usbd.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wdt.c create mode 100644 bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wwdt.c create mode 100644 bsp/nuvoton/libraries/nuc980/README.md create mode 100644 bsp/nuvoton/libraries/nuc980/SConscript create mode 100644 bsp/nuvoton/libraries/nuc980/Script/NUC980xx41.ini create mode 100644 bsp/nuvoton/libraries/nuc980/Script/NUC980xx61.ini create mode 100644 bsp/nuvoton/libraries/nuc980/Script/NUC980xx71.ini create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/SConscript create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_ebi.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_ebi.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_etimer.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_pwm.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_qspi.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_qspi.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_scuart.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_spi.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_spi.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_systick.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_uart.c create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_uart.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_wdt.c create mode 100644 bsp/nuvoton/nk-980iot/.config create mode 100644 bsp/nuvoton/nk-980iot/Kconfig create mode 100644 bsp/nuvoton/nk-980iot/README.md create mode 100644 bsp/nuvoton/nk-980iot/SConscript create mode 100644 bsp/nuvoton/nk-980iot/SConstruct create mode 100644 bsp/nuvoton/nk-980iot/applications/SConscript create mode 100644 bsp/nuvoton/nk-980iot/applications/main.c create mode 100644 bsp/nuvoton/nk-980iot/applications/mnt.c create mode 100644 bsp/nuvoton/nk-980iot/board/Kconfig create mode 100644 bsp/nuvoton/nk-980iot/board/SConscript create mode 100644 bsp/nuvoton/nk-980iot/board/board.h create mode 100644 bsp/nuvoton/nk-980iot/board/board_dev.c create mode 100644 bsp/nuvoton/nk-980iot/board/fal_cfg.h create mode 100644 bsp/nuvoton/nk-980iot/board/nu_pin_init.c create mode 100644 bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld create mode 100644 bsp/nuvoton/nk-980iot/linking_scripts/nuc980.sct create mode 100644 bsp/nuvoton/nk-980iot/rtconfig.py create mode 100644 bsp/nuvoton/nk-980iot/template.uvproj create mode 100644 bsp/nuvoton/nk-980iot/template.uvprojx diff --git a/bsp/nuvoton/README.md b/bsp/nuvoton/README.md index f4dc822223..1a5b3c578e 100644 --- a/bsp/nuvoton/README.md +++ b/bsp/nuvoton/README.md @@ -3,5 +3,6 @@ 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 | +| [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 | diff --git a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_can.c b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_can.c index 8186886c2f..741451add4 100644 --- a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_can.c +++ b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_can.c @@ -1148,11 +1148,11 @@ int32_t CAN_SetRxMsgAndMsk(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, 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 = 0ul; + uint32_t i; uint32_t u32TimeOutCount; uint32_t u32EOB_Flag = 0ul; - for(i = 1ul; i < u32MsgCount; i++) + for(i = 1ul; i <= u32MsgCount; i++) { u32TimeOutCount = 0ul; diff --git a/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h b/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h index 7b8795b72e..01d00171ee 100644 --- a/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h +++ b/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h @@ -141,7 +141,7 @@ typedef int (UAC_CB_FUNC)(struct uac_dev_t *dev, uint8_t *data, int len); /*! /* */ /*------------------------------------------------------------------*/ extern void usbh_core_init(void); -extern int usbh_pooling_root_hubs(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); diff --git a/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c b/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c index abfb4891c2..eed2e5ae2b 100644 --- a/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c +++ b/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c @@ -80,7 +80,7 @@ void usbh_core_init() * @retval 0 No any hub port status changes found. * @retval 1 There's hub port status changes. */ -int usbh_pooling_root_hubs(void) +int usbh_polling_root_hubs(void) { int ret, change = 0; diff --git a/bsp/nuvoton/libraries/m480/rtt_port/Kconfig b/bsp/nuvoton/libraries/m480/rtt_port/Kconfig index 2e5fd7a81b..22523e90b4 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/m480/rtt_port/Kconfig @@ -941,6 +941,13 @@ config SOC_SERIES_M480 select RT_USING_USB_HOST select RT_USBH_MSTORAGE + if BSP_USING_USBH || BSP_USING_HSUSBH + config NU_USBHOST_HUB_POLLING_INTERVAL + int "USB Root Hub Polling Interval(in Mili-seconds)" + range 100 2000 + default 100 + endif + config BSP_USING_HSOTG bool "Enable High-Speed USB On-The-Go(HSOTG)" select BSP_USING_HSUSBH diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_bpwm_capture.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_bpwm_capture.c index c7235fe7ae..a28c1c1d5d 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_bpwm_capture.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_bpwm_capture.c @@ -12,6 +12,7 @@ #include #if defined(BSP_USING_BPWM_CAPTURE) +#if ((BSP_USING_BPWM0_CAPTURE_CHMSK+BSP_USING_BPWM1_CAPTURE_CHMSK)!=0) #include #include @@ -211,7 +212,7 @@ static rt_err_t nu_bpwm_init(nu_capture_t *nu_capture) /* Enable BPWM0 clock */ SYS_UnlockReg(); CLK_EnableModuleClock(BPWM0_MODULE); - CLK_SetModuleClock(BPWM0_MODULE, CLK_CLKSEL2_BPWM0SEL_PLL, (uint32_t)NULL); + CLK_SetModuleClock(BPWM0_MODULE, CLK_CLKSEL2_BPWM0SEL_PLL, 0); SYS_LockReg(); bpwm_config(nu_capture); bBPWM0Inited = RT_TRUE; @@ -225,7 +226,7 @@ static rt_err_t nu_bpwm_init(nu_capture_t *nu_capture) /* Enable BPWM1 clock */ SYS_UnlockReg(); CLK_EnableModuleClock(BPWM1_MODULE); - CLK_SetModuleClock(BPWM1_MODULE, CLK_CLKSEL2_BPWM1SEL_PLL, (uint32_t)NULL); + CLK_SetModuleClock(BPWM1_MODULE, CLK_CLKSEL2_BPWM1SEL_PLL, 0); SYS_LockReg(); bpwm_config(nu_capture); bBPWM1Inited = RT_TRUE; @@ -330,4 +331,5 @@ static int nu_bpwm_capture_device_init(void) } 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/m480/rtt_port/drv_can.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c index a0fd7d37fa..a027328d1d 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c @@ -369,7 +369,7 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(can_base, MSG(i + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(can_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); } @@ -378,7 +378,7 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(can_base, MSG(i + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(can_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); } @@ -439,7 +439,7 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) } break; default: - return -(RT_EINVAL); + return -(RT_EINVAL); } @@ -507,7 +507,8 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn #ifdef RT_CAN_USING_HDR /* Hardware filter messages are valid */ - can->hdr->connected = 1; + pmsg->hdr = boxno - RX_MSG_ID_INDEX; + can->hdr[pmsg->hdr].connected = 1; #endif /* Standard ID (11 bits)*/ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_clk.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_clk.c index abbefbeebe..f61852a0dc 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_clk.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_clk.c @@ -89,64 +89,44 @@ static struct rt_pm_ops ops = struct rt_device pm; - +/* Sleep and power-down mapping */ +const static uint32_t g_au32SleepingMode[PM_SLEEP_MODE_MAX] = +{ + 0, + 0, + CONFIG_MODE_LIGHT, + CONFIG_MODE_DEEP, + CONFIG_MODE_STANDBY, + CONFIG_MODE_SHUTDOWN +}; /* pm sleep() entry */ static void pm_sleep(struct rt_pm *pm, rt_uint8_t mode) { - SYS_UnlockReg(); + RT_ASSERT(mode < PM_SLEEP_MODE_MAX); + + if ((mode == PM_SLEEP_MODE_NONE) || (mode == PM_SLEEP_MODE_IDLE)) + return; - 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: - - CLK_SetPowerDownMode(CONFIG_MODE_LIGHT); - CLK_PowerDown(); - break; - - case PM_SLEEP_MODE_DEEP: - - CLK_SetPowerDownMode(CONFIG_MODE_DEEP); - CLK_PowerDown(); - break; - - case PM_SLEEP_MODE_STANDBY: - -#if defined (NU_CLK_INVOKE_WKTMR) - - /* Enable wake-up timer with pre-defined interval if it is invoked */ - CLK_SET_WKTMR_INTERVAL(WKTMR_INTERVAL); - CLK_ENABLE_WKTMR(); -#endif - CLK_SetPowerDownMode(CONFIG_MODE_STANDBY); - CLK_PowerDown(); - break; - - case PM_SLEEP_MODE_SHUTDOWN: + SYS_UnlockReg(); #if defined (NU_CLK_INVOKE_WKTMR) + if ((mode == PM_SLEEP_MODE_SHUTDOWN) || (mode == PM_SLEEP_MODE_STANDBY)) + { /* Enable wake-up timer with pre-defined interval if it is invoked */ CLK_SET_WKTMR_INTERVAL(WKTMR_INTERVAL); CLK_ENABLE_WKTMR(); + } #endif - CLK_SetPowerDownMode(CONFIG_MODE_SHUTDOWN); - CLK_PowerDown(); - break; - default: - RT_ASSERT(0); - break; - } + CLK_SetPowerDownMode(g_au32SleepingMode[mode]); + CLK_PowerDown(); SYS_LockReg(); } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c index 50c056730e..cd16b33f70 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c @@ -25,6 +25,11 @@ /* 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; @@ -85,7 +90,6 @@ static rt_uint32_t nu_crc_run( return u32CalChecksum; } - rt_err_t nu_crc_init(void) { SYS_ResetModule(CRC_RST); @@ -103,30 +107,29 @@ rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_siz //select CRC operation mode switch (ctx->crc_cfg.poly) { - case 0x04C11DB7: + case CRC_32_POLY: u32OpMode = CRC_32; break; - case 0x00001021: + case CRC_CCITT_POLY: u32OpMode = CRC_CCITT; break; - case 0x00008005: + case CRC_16_POLY: u32OpMode = CRC_16; break; - case 0x00000007: + 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 - 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 - - //Calcluate CRC checksum, using config's last value as CRC seed + //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 vaule + //update CRC result to config's last value ctx->crc_cfg.last_val = crc_result; return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout; } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.h b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.h index 04c2038c07..a792b93319 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.h +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.h @@ -17,5 +17,4 @@ 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/m480/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c index 6cc1f0b309..7c84387b84 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c @@ -15,10 +15,9 @@ #if ((defined(BSP_USING_CRYPTO) || defined(BSP_USING_TRNG) || defined(BSP_USING_CRC)) && defined(RT_USING_HWCRYPTO)) -#include - #include #include +#include #include "NuMicro.h" #include @@ -32,6 +31,14 @@ /* Private typedef --------------------------------------------------------------*/ +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); @@ -50,9 +57,6 @@ static const struct rt_hwcrypto_ops nu_hwcrypto_ops = /* Crypto engine operation ------------------------------------------------------------*/ #if defined(BSP_USING_CRYPTO) -//define NU_HWCRYPTO_NOT_ALIGN_CHECK to disable plain/cipher buffer address alignment checking -//#define NU_HWCRYPTO_NOT_ALIGN_CHECK - #define NU_HWCRYPTO_DES_3KEYS 1 #define NU_HWCRYPTO_DES_NO3KEYS 0 #define NU_HWCRYPTO_AES_NAME "nu_AES" @@ -102,6 +106,8 @@ void CRYPTO_IRQHandler() { if (AES_GET_INT_FLAG(CRPT)) { + if (CRPT->INTSTS & (CRPT_INTSTS_AESEIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk | (0x1ul << 21)))) + rt_kprintf("AES ERROR\n"); s_AES_done = 1; AES_CLR_INT_FLAG(CRPT); } @@ -114,6 +120,8 @@ void CRYPTO_IRQHandler() if (SHA_GET_INT_FLAG(CRPT)) { + if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk | (0x1ul << 9)))) + rt_kprintf("SHA ERROR\n"); s_SHA_done = 1; SHA_CLR_INT_FLAG(CRPT); } @@ -218,8 +226,11 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw 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]; - if ((symmetric_info->length % 16) != 0) + if ((symmetric_info->length % 4) != 0) { return -RT_EINVAL; } @@ -267,12 +278,8 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw in = (unsigned char *)symmetric_info->in; out = (unsigned char *)symmetric_info->out; -#if !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) - unsigned char in_align_flag = 0; - unsigned char out_align_flag = 0; - - //Checking in/out data buffer address alignment or not - if (((rt_uint32_t)in % 4) != 0) + //Checking in/out data buffer address not alignment or out of SRAM + if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)in < SRAM_BASE) || ((rt_uint32_t)in > SRAM_END)) { in = rt_malloc(symmetric_info->length); if (in == RT_NULL) @@ -281,11 +288,11 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw return -RT_ENOMEM; } - memcpy(in, symmetric_info->in, symmetric_info->length); + rt_memcpy(in, symmetric_info->in, symmetric_info->length); in_align_flag = 1; } - if (((rt_uint32_t)out % 4) != 0) + if (((rt_uint32_t)out % 4) != 0 || ((rt_uint32_t)out < SRAM_BASE) || ((rt_uint32_t)out > SRAM_END)) { out = rt_malloc(symmetric_info->length); if (out == RT_NULL) @@ -298,14 +305,35 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw out_align_flag = 1; } -#endif + + 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 !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) + 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) { - memcpy(symmetric_info->out, out, symmetric_info->length); + rt_memcpy(symmetric_info->out, out, symmetric_info->length); rt_free(out); } @@ -313,7 +341,6 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw { rt_free(in); } -#endif return RT_EOK; } @@ -371,6 +398,8 @@ static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw 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) { @@ -413,12 +442,8 @@ static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw in = (unsigned char *)symmetric_info->in; out = (unsigned char *)symmetric_info->out; -#if !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) - unsigned char in_align_flag = 0; - unsigned char out_align_flag = 0; - - //Checking in/out data buffer address alignment or not - if (((rt_uint32_t)in % 4) != 0) + //Checking in/out data buffer address not alignment or out of SRAM + if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)in < SRAM_BASE) || ((rt_uint32_t)in > SRAM_END)) { in = rt_malloc(symmetric_info->length); if (in == RT_NULL) @@ -427,11 +452,11 @@ static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw return -RT_ENOMEM; } - memcpy(in, symmetric_info->in, symmetric_info->length); + rt_memcpy(in, symmetric_info->in, symmetric_info->length); in_align_flag = 1; } - if (((rt_uint32_t)out % 4) != 0) + if (((rt_uint32_t)out % 4) != 0 || ((rt_uint32_t)out < SRAM_BASE) || ((rt_uint32_t)out > SRAM_END)) { out = rt_malloc(symmetric_info->length); if (out == RT_NULL) @@ -444,14 +469,12 @@ static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw out_align_flag = 1; } -#endif 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 !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) if (out_align_flag) { - memcpy(symmetric_info->out, out, symmetric_info->length); + rt_memcpy(symmetric_info->out, out, symmetric_info->length); rt_free(out); } @@ -459,12 +482,53 @@ static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw { rt_free(in); } -#endif return RT_EOK; } +#define CRPT_HMAC_CTL_DMAFIRST_Pos (4) /*!< CRPT_T::HMAC_CTL: DMAFIRST Position */ +#define CRPT_HMAC_CTL_DMAFIRST_Msk (0x1ul << CRPT_HMAC_CTL_DMAFIRST_Pos) /*!< CRPT_T::HMAC_CTL: DMAFIRST Mask */ + +static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t u32Mode) +{ + SHA_Open(CRPT, u32OpMode, SHA_IN_OUT_SWAP, 0); + + //Setup SHA DMA + SHA_SetDMATransfer(CRPT, u32SrcAddr, u32Len); + SHA_CLR_INT_FLAG(CRPT); + + //Start SHA + s_SHA_done = 0; + + if (u32Mode == CRYPTO_DMA_FIRST) + { + if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) + { + //M480MD version + u32Mode = CRYPTO_DMA_CONTINUE; + } + else + { + //M480LD version + CRPT->HMAC_CTL |= CRPT_HMAC_CTL_DMAFIRST_Msk; + } + } + else + { + if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) != 0x0) + { + //M480LD version + CRPT->HMAC_CTL &= ~CRPT_HMAC_CTL_DMAFIRST_Msk; + } + } + + SHA_Start(CRPT, u32Mode); + + while (!s_SHA_done) {}; +} + static rt_err_t nu_sha_hash_run( + S_SHA_CONTEXT *psSHACtx, uint32_t u32OpMode, uint8_t *pu8InData, uint32_t u32DataLen @@ -472,16 +536,82 @@ static rt_err_t nu_sha_hash_run( { rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER); - //Using SHA - SHA_Open(CRPT, u32OpMode, SHA_IN_OUT_SWAP, 0); + uint8_t *pu8SrcAddr = (uint8_t *)pu8InData; + uint32_t u32CopyLen = 0; - //Setup SHA DMA - SHA_SetDMATransfer(CRPT, (uint32_t)pu8InData, u32DataLen); - SHA_CLR_INT_FLAG(CRPT); - //Start SHA - s_SHA_done = 0; - SHA_Start(CRPT, CRYPTO_DMA_ONE_SHOT); - while (!s_SHA_done) {}; + 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(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 & 3) //address not aligned 4 + { + psSHACtx->pu8SHATempBuf = rt_malloc(psSHACtx->u32BlockSize); + + if (psSHACtx->pu8SHATempBuf == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); + rt_mutex_release(&s_SHA_mutex); + 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(psSHACtx->u32BlockSize); + + if (psSHACtx->pu8SHATempBuf == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); + rt_mutex_release(&s_SHA_mutex); + return -RT_ENOMEM; + } + + psSHACtx->u32SHATempBufLen = 0; + } + + rt_memcpy(psSHACtx->pu8SHATempBuf, pu8SrcAddr, u32DataLen); + psSHACtx->u32SHATempBufLen += u32DataLen; + } rt_mutex_release(&s_SHA_mutex); @@ -492,6 +622,7 @@ static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t * { uint32_t u32SHAOpMode; unsigned char *nu_in; + unsigned char in_align_flag = 0; //Select SHA operation mode switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) @@ -517,11 +648,8 @@ static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t * nu_in = (unsigned char *)in; -#if !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) - unsigned char in_align_flag = 0; - - //Checking in data buffer address alignment or not - if (((rt_uint32_t)nu_in % 4) != 0) + //Checking in data buffer address not alignment or out of SRAM + if (((rt_uint32_t)nu_in % 4) != 0 || ((rt_uint32_t)nu_in < SRAM_BASE) || ((rt_uint32_t)nu_in > SRAM_END)) { nu_in = rt_malloc(length); if (nu_in == RT_NULL) @@ -530,19 +658,16 @@ static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t * return -RT_ENOMEM; } - memcpy(nu_in, in, length); + rt_memcpy(nu_in, in, length); in_align_flag = 1; } -#endif - nu_sha_hash_run(u32SHAOpMode, nu_in, length); + nu_sha_hash_run(hash_ctx->parent.contex, u32SHAOpMode, nu_in, length); -#if !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) if (in_align_flag) { rt_free(nu_in); } -#endif return RT_EOK; } @@ -550,35 +675,43 @@ static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t * 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 = 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; @@ -590,9 +723,6 @@ static rt_err_t nu_sha_finish(struct hwcrypto_hash *hash_ctx, rt_uint8_t *out, r nu_out = (unsigned char *)out; -#if !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) - unsigned char out_align_flag = 0; - //Checking out data buffer address alignment or not if (((rt_uint32_t)nu_out % 4) != 0) { @@ -605,17 +735,31 @@ static rt_err_t nu_sha_finish(struct hwcrypto_hash *hash_ctx, rt_uint8_t *out, r out_align_flag = 1; } -#endif + + 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(psSHACtx->pu8SHATempBuf); + psSHACtx->pu8SHATempBuf = RT_NULL; + psSHACtx->u32SHATempBufLen = 0; + } + else + { + SHABlockUpdate(u32SHAOpMode, (uint32_t)NULL, 0, CRYPTO_DMA_LAST); + } SHA_Read(CRPT, (uint32_t *)nu_out); -#if !defined(NU_HWCRYPTO_NOT_ALIGN_CHECK) if (out_align_flag) { - memcpy(out, out, length); - rt_free(out); + rt_memcpy(out, nu_out, length); + rt_free(nu_out); } -#endif return RT_EOK; } @@ -728,7 +872,12 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) case HWCRYPTO_TYPE_SHA1: { - ctx->contex = RT_NULL; + 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; @@ -736,7 +885,12 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) case HWCRYPTO_TYPE_SHA2: { - ctx->contex = RT_NULL; + 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; @@ -758,7 +912,6 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) #endif /* BSP_USING_CRYPTO */ - default: res = -RT_ERROR; break; @@ -801,6 +954,32 @@ static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx) break; } #endif /* !BSP_USING_TRNG */ +#if defined(BSP_USING_CRYPTO) + case HWCRYPTO_TYPE_SHA1: + case HWCRYPTO_TYPE_SHA2: + { + S_SHA_CONTEXT *psSHACtx = (S_SHA_CONTEXT *)ctx->contex; + + if (psSHACtx->pu8SHATempBuf) + { + rt_free(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; + } +#endif default: break; diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_ecap.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_ecap.c index c714338d9e..0e354373af 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_ecap.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_ecap.c @@ -12,6 +12,7 @@ #include #if defined(BSP_USING_ECAP) +#if ((BSP_USING_ECAP0_CHMSK+BSP_USING_ECAP1_CHMSK)!=0) #include #include @@ -262,7 +263,7 @@ static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputca else /* Overrun case */ fTempCnt = nu_capture->u32CurrentCnt + ((0x1000000 - nu_capture->u32LastCnt) + 1); - *pulsewidth_us =(int)(fTempCnt * nu_capture->ecap_dev->fUsPerTick); + *pulsewidth_us = (int)(fTempCnt * nu_capture->ecap_dev->fUsPerTick); nu_capture->u32LastCnt = nu_capture->u32CurrentCnt; @@ -430,7 +431,7 @@ static int nu_ecap_capture_device_init(void) #if (BSP_USING_ECAP0_CHMSK!=0) if (BSP_USING_ECAP0_CHMSK & (0x1 << i)) { - nu_ecap0_capture[i] = (nu_capture_t*)rt_malloc(sizeof(nu_capture_t)); + nu_ecap0_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t)); ecap_init(nu_ecap0_capture[i], i, &nu_ecap0_dev, nu_ecap0_device_name[i]); } #endif //#if (BSP_USING_ECAP0_CHMSK!=0) @@ -438,7 +439,7 @@ static int nu_ecap_capture_device_init(void) #if (BSP_USING_ECAP1_CHMSK!=0) if (BSP_USING_ECAP1_CHMSK & (0x1 << i)) { - nu_ecap1_capture[i] = (nu_capture_t*)rt_malloc(sizeof(nu_capture_t)); + nu_ecap1_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t)); ecap_init(nu_ecap1_capture[i], i, &nu_ecap1_dev, nu_ecap1_device_name[i]); } #endif //#if (BSP_USING_ECAP1_CHMSK!=0) @@ -447,5 +448,5 @@ static int nu_ecap_capture_device_init(void) return 0; } INIT_DEVICE_EXPORT(nu_ecap_capture_device_init); - +#endif //#if ((BSP_USING_ECAP0_CHMSK+BSP_USING_ECAP1_CHMSK)!=0) #endif //#if defined(BSP_USING_ECAP) 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 af21f643ec..c95febf8eb 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_epwm_capture.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_epwm_capture.c @@ -12,6 +12,7 @@ #include #if defined(BSP_USING_EPWM_CAPTURE) +#if ((BSP_USING_EPWM0_CAPTURE_CHMSK+BSP_USING_EPWM1_CAPTURE_CHMSK)!=0) #include #include @@ -73,7 +74,7 @@ static rt_err_t CalPulseWidth(nu_capture_t *nu_capture) bWrapAroundFlag = RT_TRUE; } - /* Read the capture counter value if falling/risning edge */ + /* Read the capture counter value if falling/rising edge */ if (EPWM_GetCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel) == 1)//Rising edge { EPWM_ClearCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_RISING_LATCH); @@ -294,7 +295,7 @@ void EPWM1P1_IRQHandler(void) void EPWM1P2_IRQHandler(void) { /* enter interrupt */ - rt_interrupt_enter() + rt_interrupt_enter(); /* Avoid excessive iteration by monitoring enabled channels */ #if (BSP_USING_EPWM1_CAPTURE_CHMSK&(0x1<epwm, nu_capture->u8Channel, 1000, 0); /* Enable capture rising/falling edge interrupt */ @@ -500,10 +501,10 @@ int nu_epwm_capture_device_init(void) rt_device_inputcapture_register(&nu_epwm1_capture[i].parent, nu_epwm1_device_name[i], &nu_epwm1_capture[i]); } } -#endif //#if (BSP_USING_EPWM1_CAPTURE_CHMSK!=0) +#endif //#if (BSP_USING_EPWM1_CAPTURE_CHMSK!=0) return 0; } INIT_DEVICE_EXPORT(nu_epwm_capture_device_init); - +#endif //#if ((BSP_USING_EPWM0_CAPTURE_CHMSK+BSP_USING_EPWM1_CAPTURE_CHMSK)!=0) #endif //#if defined(BSP_USING_EPWM_CAPTURE) diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c index e0e3b5f56b..a5a97bea1b 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c @@ -159,7 +159,7 @@ int nu_fmc_erase(long addr, size_t size) uint32_t addr_end = addr + size; #if defined(NU_SUPPORT_NONALIGN) - uint8_t *page_sdtemp = RT_NULL; + uint8_t *page_sdtemp = RT_NULL; uint8_t *page_edtemp = RT_NULL; @@ -316,6 +316,11 @@ static int nu_fmc_init(void) g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_FIFO); + /* PKG_USING_FAL */ +#if defined(PKG_USING_FAL) + fal_init(); +#endif + return (int)RT_EOK; } INIT_APP_EXPORT(nu_fmc_init); diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_gpio.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_gpio.c index 6e752332a4..d00677392d 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_gpio.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_gpio.c @@ -19,6 +19,7 @@ #include #include #include +#include /* Private define ---------------------------------------------------------------*/ @@ -34,6 +35,7 @@ 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]; @@ -45,7 +47,7 @@ static struct rt_pin_ops nu_gpio_ops = nu_gpio_attach_irq, nu_gpio_detach_irq, nu_gpio_irq_enable, - RT_NULL, + nu_gpio_pin_get, }; static IRQn_Type au32GPIRQ[NU_PORT_CNT] = {GPA_IRQn, GPB_IRQn, GPC_IRQn, GPD_IRQn, GPE_IRQn, GPF_IRQn, GPG_IRQn, GPH_IRQn}; @@ -102,6 +104,31 @@ static void pin_irq_hdr(rt_uint32_t irq_status, rt_uint32_t port_index) } } +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] <= 'H') + return ((name[1] - 'A') * 0x10) + number; + + if (name[1] >= 'a' && name[1] <= 'h') + 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_T *PORT; diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c index 0c96c5336f..ecf78a5c70 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c @@ -202,9 +202,9 @@ static rt_err_t nu_i2c_send_address(nu_i2c_bus_t *nu_i2c, 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) + 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; diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c index 6e3a86ae31..735c991089 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c @@ -54,7 +54,6 @@ struct nu_pdma_memfun_actor { int m_i32ChannID; uint32_t m_u32Result; - uint32_t m_u32TrigTransferCnt; rt_sem_t m_psSemMemFun; } ; typedef struct nu_pdma_memfun_actor *nu_pdma_memfun_actor_t; @@ -553,6 +552,8 @@ 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 ) + goto exit_nu_pdma_desc_setup; psPeriphCtl = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl; @@ -701,9 +702,10 @@ static rt_err_t nu_pdma_sgtbls_valid(nu_pdma_desc_t head) node = (nu_pdma_desc_t)(node->NEXT + PDMA->SCATBA); - } while (((uint32_t)node != PDMA->SCATBA) && (node != head)); + } + while (((uint32_t)node != PDMA->SCATBA) && (node != head)); - return RT_EOK; + return RT_EOK; } static void _nu_pdma_transfer(int i32ChannID, uint32_t u32Peripheral, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us) @@ -718,7 +720,7 @@ static void _nu_pdma_transfer(int i32ChannID, uint32_t u32Peripheral, nu_pdma_de PDMA_SetTransferMode(PDMA, i32ChannID, u32Peripheral, - (head != NULL) ? 1 : 0, + (head->NEXT != 0) ? 1 : 0, (uint32_t)head); /* If peripheral is M2M, trigger it. */ @@ -747,7 +749,7 @@ rt_err_t nu_pdma_transfer(int i32ChannID, uint32_t u32DataWidth, uint32_t u32Add if (ret != RT_EOK) goto exit_nu_pdma_transfer; - _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, NULL, u32IdleTimeout_us); + _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, &PDMA->DSCT[i32ChannID], u32IdleTimeout_us); ret = RT_EOK; @@ -765,7 +767,7 @@ rt_err_t nu_pdma_sg_transfer(int i32ChannID, nu_pdma_desc_t head, uint32_t u32Id 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. */ + 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; @@ -912,11 +914,14 @@ static int nu_pdma_memfun_employ(void) return idx; } -static rt_size_t nu_pdma_memfun(void *dest, void *src, uint32_t u32DataWidth, unsigned int count, nu_pdma_memctrl_t eMemCtl) +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 */ @@ -925,37 +930,51 @@ static rt_size_t nu_pdma_memfun(void *dest, void *src, uint32_t u32DataWidth, un psMemFunActor = &nu_pdma_memfun_actor_arr[idx]; - psMemFunActor->m_u32TrigTransferCnt = count; + do + { - /* Set PDMA memory control to eMemCtl. */ - nu_pdma_channel_memctrl_set(psMemFunActor->m_i32ChannID, eMemCtl); + u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt; - /* 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); + /* Set PDMA memory control to eMemCtl. */ + nu_pdma_channel_memctrl_set(psMemFunActor->m_i32ChannID, eMemCtl); - psMemFunActor->m_u32Result = 0; + /* 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); - /* Trigger it */ - nu_pdma_transfer(psMemFunActor->m_i32ChannID, u32DataWidth, (uint32_t)src, (uint32_t)dest, count, 0); + psMemFunActor->m_u32Result = 0; - /* Wait it done. */ - rt_sem_take(psMemFunActor->m_psSemMemFun, RT_WAITING_FOREVER); + /* 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); - /* Give result if get NU_PDMA_EVENT_TRANSFER_DONE.*/ - if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_TRANSFER_DONE) - { - ret = psMemFunActor->m_u32TrigTransferCnt; - } - else - { - ret = psMemFunActor->m_u32TrigTransferCnt - nu_pdma_non_transfer_count_get(psMemFunActor->m_i32ChannID); - } + /* Wait it done. */ + rt_sem_take(psMemFunActor->m_psSemMemFun, RT_WAITING_FOREVER); - /* Terminate it if get ABORT event */ - if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_ABORT) - { - nu_pdma_channel_terminate(psMemFunActor->m_i32ChannID); + /* 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); @@ -979,10 +998,34 @@ rt_size_t nu_pdma_mempush(void *dest, void *src, uint32_t data_width, unsigned i void *nu_pdma_memcpy(void *dest, void *src, unsigned int count) { - if (count == nu_pdma_memfun(dest, src, 8, count, eMemCtl_SrcInc_DstInc)) + 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; - else - return NULL; + +exit_nu_pdma_memcpy: + + return NULL; } /** diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.h b/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.h index e379323633..35082be311 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.h +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.h @@ -31,6 +31,7 @@ #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 { diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_rtc.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_rtc.c index 361ee87755..804c0a0a0c 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_rtc.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_rtc.c @@ -52,21 +52,21 @@ 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); + 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_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); + 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 ------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_spi.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_spi.c index c3fc788203..e6a12ecced 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_spi.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_spi.c @@ -342,25 +342,38 @@ exit_nu_pdma_spi_tx_config: 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; - result = nu_pdma_spi_rx_config(spi_bus, recv_addr, length, bytes_per_word); - RT_ASSERT(result == RT_EOK); - result = nu_pdma_spi_tx_config(spi_bus, send_addr, length, bytes_per_word); - RT_ASSERT(result == RT_EOK); + 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); - /* Trigger TX/RX PDMA transfer. */ - SPI_TRIGGER_TX_RX_PDMA(spi_base); + 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); - /* Wait RX-PDMA transfer done */ - rt_sem_take(spi_bus->m_psSemBus, RT_WAITING_FOREVER); + /* Trigger TX/RX PDMA transfer. */ + SPI_TRIGGER_TX_RX_PDMA(spi_base); - /* Stop TX/RX DMA transfer. */ - SPI_DISABLE_TX_RX_PDMA(spi_base); + /* Wait RX-PDMA transfer done */ + rt_sem_take(spi_bus->m_psSemBus, RT_WAITING_FOREVER); - return result; + /* 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) diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_timer_capture.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_timer_capture.c index 5c32b90aa2..4630378760 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_timer_capture.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_timer_capture.c @@ -13,6 +13,10 @@ #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 @@ -150,8 +154,6 @@ static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputca static rt_err_t nu_timer_init(nu_capture_t *nu_capture) { - rt_err_t ret = RT_ERROR; - SYS_UnlockReg(); #if defined(BSP_USING_TIMER0_CAPTURE) @@ -160,8 +162,6 @@ static rt_err_t nu_timer_init(nu_capture_t *nu_capture) /* Enable TIMER0 clock */ CLK_EnableModuleClock(TMR0_MODULE); CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_PCLK0, 0); - - ret = RT_EOK; goto exit_nu_timer_init; } #endif @@ -171,8 +171,6 @@ static rt_err_t nu_timer_init(nu_capture_t *nu_capture) /* Enable TIMER1 clock */ CLK_EnableModuleClock(TMR1_MODULE); CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK0, 0); - - ret = RT_EOK; goto exit_nu_timer_init; } #endif @@ -182,8 +180,6 @@ static rt_err_t nu_timer_init(nu_capture_t *nu_capture) /* Enable TIMER2 clock */ CLK_EnableModuleClock(TMR2_MODULE); CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL1_TMR2SEL_PCLK1, 0); - - ret = RT_EOK; goto exit_nu_timer_init; } #endif @@ -193,12 +189,17 @@ static rt_err_t nu_timer_init(nu_capture_t *nu_capture) /* 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 -(ret); + return RT_EOK; } static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture) @@ -241,6 +242,9 @@ static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) /* 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); @@ -318,5 +322,5 @@ static int nu_timer_capture_device_init(void) 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/m480/rtt_port/drv_trng.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c index 778a14cb3d..ec8f49d71b 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c @@ -15,8 +15,8 @@ #if (defined(BSP_USING_TRNG) && defined(RT_HWCRYPTO_USING_RNG)) #include -#include #include "NuMicro.h" +#include #define NU_CRYPTO_TRNG_NAME "nu_TRNG" diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.h b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.h index 7677323a47..c9d3a90ee4 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.h +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.h @@ -18,4 +18,3 @@ void nu_trng_open(void); rt_uint32_t nu_trng_rand(struct hwcrypto_rng *ctx); #endif - diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_uart.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_uart.c index d8f9ba1777..d694ab7d8c 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_uart.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_uart.c @@ -546,7 +546,7 @@ static rt_err_t nu_pdma_uart_rx_config(struct rt_serial_device *serial, uint8_t nu_pdma_uart_rx_cb, (void *)serial, NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT); - if ( result != RT_EOK ) + if (result != RT_EOK) { goto exit_nu_pdma_uart_rx_config; } @@ -557,7 +557,7 @@ static rt_err_t nu_pdma_uart_rx_config(struct rt_serial_device *serial, uint8_t (uint32_t)pu8Buf, i32TriggerLen, 1000); //Idle-timeout, 1ms - if ( result != RT_EOK ) + if (result != RT_EOK) { goto exit_nu_pdma_uart_rx_config; } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbd.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbd.c index 2c815bd4f6..b38d0b9c18 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbd.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbd.c @@ -364,7 +364,7 @@ __STATIC_INLINE void _USBD_IRQHandler(void) /* Clear event flag */ USBD_CLR_INT_FLAG(USBD_INTSTS_EP0); - if ( (USBD_GET_ADDR() == 0) + if ((USBD_GET_ADDR() == 0) && (nu_usbd.address_tmp) ) { diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c index dba7a4e442..f168a3fcd4 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c @@ -22,6 +22,10 @@ #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 //USB1.1 + USB2.0 port #define NU_MAX_USBH_PIPE 16 #define NU_USBH_THREAD_STACK_SIZE 2048 @@ -51,6 +55,7 @@ typedef struct nu_port_ctrl struct nu_usbh_dev { uhcd_t uhcd; + rt_thread_t polling_thread; S_NU_RH_PORT_CTRL asPortCtrl[NU_MAX_USBH_PORT]; }; @@ -290,7 +295,6 @@ static rt_err_t nu_open_pipe(upipe_t pipe) static rt_err_t nu_close_pipe(upipe_t pipe) { - int i; S_NU_RH_PORT_CTRL *psPortCtrl; S_NU_PORT_DEV *psPortDev; @@ -309,6 +313,7 @@ static rt_err_t nu_close_pipe(upipe_t pipe) { if (psPortDev->pUDev) { + int i; for (i = 0; i < NU_MAX_USBH_PIPE; i++) { if (psPortDev->apsEPInfo[i] != NULL) @@ -320,7 +325,6 @@ static rt_err_t nu_close_pipe(upipe_t pipe) free_device(psPortDev->pUDev); psPortDev->pUDev = NULL; } - psPortDev->port_num = 0; } } @@ -615,8 +619,8 @@ static void nu_usbh_rh_thread_entry(void *parameter) { while (1) { - usbh_pooling_root_hubs(); - rt_thread_delay(10); + usbh_polling_root_hubs(); + rt_thread_mdelay(NU_USBHOST_HUB_POLLING_INTERVAL); } } @@ -674,6 +678,8 @@ static void nu_hcd_disconnect_callback( return; } + port_index = i + 1; + for (i = 0; i < NU_MAX_USBH_PIPE; i++) { if (psPortCtrl->sRHPortDev.apsEPInfo[i] != NULL) @@ -682,10 +688,9 @@ static void nu_hcd_disconnect_callback( } } - port_index = i + 1; psPortCtrl->sRHPortDev.pUDev = NULL; - RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnnect\n")); + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnect\n")); rt_usbh_root_hub_disconnect_handler(s_sUSBHDev.uhcd, port_index); } @@ -701,22 +706,21 @@ static struct uhcd_ops nu_uhcd_ops = static rt_err_t nu_hcd_init(rt_device_t device) { - rt_thread_t thread; - + 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_pooling_root_hubs(); + usbh_polling_root_hubs(); //create thread for polling usbh port status /* create usb hub thread */ - thread = rt_thread_create("usbh_drv", nu_usbh_rh_thread_entry, RT_NULL, + pNuUSBHDev->polling_thread = rt_thread_create("usbh_drv", nu_usbh_rh_thread_entry, RT_NULL, NU_USBH_THREAD_STACK_SIZE, 8, 20); - if (thread != RT_NULL) + if ( pNuUSBHDev->polling_thread != RT_NULL) { /* startup usb host thread */ - rt_thread_startup(thread); + rt_thread_startup( pNuUSBHDev->polling_thread ); } else { @@ -742,6 +746,54 @@ 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) +{ + 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; + rt_thread_suspend(pNuUSBHDev->polling_thread); + 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) +{ + 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: + rt_thread_resume(pNuUSBHDev->polling_thread); + 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) { @@ -760,9 +812,6 @@ int nu_usbh_register(void) #endif #if defined(BSP_USING_USBH) - /* Enable USBD and OTG clock */ - CLK_EnableModuleClock(USBD_MODULE); - CLK_EnableModuleClock(OTG_MODULE); /* Set USB Host role */ SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | (0x1u << SYS_USBPHY_USBROLE_Pos); SYS->USBPHY |= SYS_USBPHY_USBEN_Msk | SYS_USBPHY_SBO_Msk ; @@ -775,11 +824,7 @@ int nu_usbh_register(void) rt_memset(&s_sUSBHDev, 0x0, sizeof(struct nu_usbh_dev)); uhcd_t uhcd = (uhcd_t)rt_malloc(sizeof(struct uhcd)); - if (uhcd == RT_NULL) - { - rt_kprintf("uhcd malloc failed\r\n"); - return -RT_ERROR; - } + RT_ASSERT(res != RT_NULL); rt_memset((void *)uhcd, 0, sizeof(struct uhcd)); @@ -792,23 +837,18 @@ int nu_usbh_register(void) s_sUSBHDev.uhcd = uhcd; res = rt_device_register(&uhcd->parent, "usbh", RT_DEVICE_FLAG_DEACTIVATE); - if (res != RT_EOK) - { - rt_kprintf("register usb host failed res = %d\r\n", res); - return -RT_ERROR; - } + RT_ASSERT(res == RT_EOK); - /*initialize the usb host functin */ + /*initialize the usb host function */ res = rt_usb_host_init(); + RT_ASSERT(res == RT_EOK); +#if defined(RT_USING_PM) + rt_pm_device_register(&uhcd->parent, &device_pm_ops); +#endif + return RT_EOK; } INIT_DEVICE_EXPORT(nu_usbh_register); #endif - - - - - - diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_uspi.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_uspi.c index c670420eb8..9c19f3007a 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_uspi.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_uspi.c @@ -493,7 +493,7 @@ static void nu_uspi_transfer(struct nu_uspi *uspi_bus, uint8_t *tx, uint8_t *rx, /* DMA transfer constrains */ if ((uspi_bus->pdma_chanid_rx >= 0) && !((uint32_t)tx % bytes_per_word) && - !((uint32_t)rx % 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); diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_wdt.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_wdt.c index 82572325d2..15521aace9 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_wdt.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_wdt.c @@ -91,16 +91,17 @@ 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); + 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 -------------------------------------------------------------*/ @@ -118,7 +119,6 @@ static struct rt_watchdog_ops ops_wdt = static struct rt_device_pm_ops device_pm_ops = { - .suspend = wdt_pm_suspend, .resume = wdt_pm_resume, .frequency_change = wdt_pm_frequency_change @@ -180,12 +180,6 @@ static void wdt_pm_resume(const struct rt_device *device, rt_uint8_t mode) } -static uint32_t wdt_get_module_clock(void) -{ - return (CLK_GetModuleClockSource(WDT_MODULE) << CLK_CLKSEL1_WDTSEL_Pos); -} - - /* device pm frequency_change() entry. */ static int wdt_pm_frequency_change(const struct rt_device *device, rt_uint8_t mode) { @@ -288,6 +282,12 @@ static rt_err_t wdt_init(rt_watchdog_t *dev) } +static uint32_t wdt_get_module_clock(void) +{ + return (CLK_GetModuleClockSource(WDT_MODULE) << CLK_CLKSEL1_WDTSEL_Pos); +} + + static uint32_t wdt_get_working_hz(void) { uint32_t clk, hz = 0; @@ -408,6 +408,7 @@ static rt_err_t wdt_control(rt_watchdog_t *dev, int cmd, void *args) case RT_DEVICE_CTRL_WDT_START: + WDT_RESET_COUNTER(); WDT_Open(MIN_TOUTSEL, WDT_RESET_DELAY_1026CLK, TRUE, TRUE); WDT_EnableInt(); break; diff --git a/bsp/nuvoton/libraries/nu_packages/Demo/SConscript b/bsp/nuvoton/libraries/nu_packages/Demo/SConscript index 311e915a57..cfebf8d0a6 100644 --- a/bsp/nuvoton/libraries/nu_packages/Demo/SConscript +++ b/bsp/nuvoton/libraries/nu_packages/Demo/SConscript @@ -5,6 +5,7 @@ group = [] if GetDepend('NU_PKG_USING_DEMO'): src = Split(""" usbd_hid_dance_mouse.c + slcd_show_tick.c """) CPPPATH = [cwd] group = DefineGroup('nu_pkgs_demo', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/nuvoton/libraries/nu_packages/Demo/usbd_hid_dance_mouse.c b/bsp/nuvoton/libraries/nu_packages/Demo/usbd_hid_dance_mouse.c index a144c85155..312183334a 100644 --- a/bsp/nuvoton/libraries/nu_packages/Demo/usbd_hid_dance_mouse.c +++ b/bsp/nuvoton/libraries/nu_packages/Demo/usbd_hid_dance_mouse.c @@ -23,13 +23,12 @@ static struct rt_thread usb_thread; ALIGN(RT_ALIGN_SIZE) -static char usb_thread_stack[512]; +static char usb_thread_stack[1024]; static struct rt_semaphore tx_sem_complete; static rt_err_t event_hid_in(rt_device_t dev, void *buffer) { - rt_sem_release(&tx_sem_complete); - return RT_EOK; + return rt_sem_release(&tx_sem_complete); } static void usb_thread_entry(void *parameter) @@ -38,6 +37,7 @@ static void usb_thread_entry(void *parameter) uint8_t u8MouseIdx = 0; uint8_t u8MoveLen=0, u8MouseMode = 1; uint8_t pu8Buf[4]; + rt_err_t result = RT_EOK; rt_device_t device = (rt_device_t)parameter; @@ -78,7 +78,8 @@ static void usb_thread_entry(void *parameter) else { /* Wait it done. */ - rt_sem_take(&tx_sem_complete, RT_WAITING_FOREVER); + result = rt_sem_take(&tx_sem_complete, RT_WAITING_FOREVER); + RT_ASSERT( result== RT_EOK ); } } // while(1) @@ -86,29 +87,27 @@ static void usb_thread_entry(void *parameter) static int dance_mouse_init(void) { - int err = 0; + rt_err_t ret = RT_EOK; rt_device_t device = rt_device_find("hidd"); RT_ASSERT(device != RT_NULL); - err = rt_device_open(device, RT_DEVICE_FLAG_WRONLY); + ret = rt_device_open(device, RT_DEVICE_FLAG_WRONLY); + RT_ASSERT(ret == RT_EOK); - if (err != RT_EOK) - { - LOG_E("open dev failed!\n"); - return -1; - } - - rt_thread_init(&usb_thread, + ret = rt_thread_init(&usb_thread, "hidd", usb_thread_entry, device, usb_thread_stack, sizeof(usb_thread_stack), 10, 20); + RT_ASSERT(ret == RT_EOK); - rt_thread_startup(&usb_thread); + ret = rt_thread_startup(&usb_thread); + RT_ASSERT(ret == RT_EOK); return 0; } INIT_APP_EXPORT(dance_mouse_init); #endif /* #if defined(RT_USB_DEVICE_HID) && (defined(BSP_USING_USBD) || defined(BSP_USING_HSUSBD)) */ + diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_ebi.c b/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_ebi.c index 440dd2b954..2ca713af6e 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_ebi.c +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_ebi.c @@ -42,6 +42,15 @@ void ili9341_send_pixel_data(rt_uint16_t color) ili9341_write_data(color); } +void ili9341_send_pixels(rt_uint16_t *pixels, int len) +{ + int i = 0; + int size = len / sizeof(rt_uint16_t); + + while (i < size) + ili9341_write_data(pixels[i]); +} + void ili9341_set_column(uint16_t StartCol, uint16_t EndCol) { ili9341_send_cmd(0x2A); diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_spi.c b/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_spi.c index f8bd8536ff..aed80b4ef4 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_spi.c +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/ili9341_spi.c @@ -54,9 +54,15 @@ static void ili9341_write_data_16bit(uint16_t data) rt_spi_transfer(&ili9341_spi_device, (const void *)&data, NULL, 2); } -void ili9341_send_pixel_data(rt_uint16_t color) +void ili9341_send_pixel_data(rt_uint16_t pixel) { - ili9341_write_data_16bit(color); + ili9341_write_data_16bit(pixel); +} + +void ili9341_send_pixels(rt_uint16_t *pixels, int len) +{ + ili9341_change_datawidth(16); + rt_spi_transfer(&ili9341_spi_device, (const void *)pixels, NULL, len); } static rt_err_t ili9341_spi_send_then_recv(struct rt_spi_device *device, diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c index c8b24d46be..40d2e53e45 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c @@ -17,6 +17,15 @@ #include #include +static struct rt_device_graphic_info g_Ili9341Info = +{ + .bits_per_pixel = 16, + .pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565, + .framebuffer = RT_NULL, + .width = XSIZE_PHYS, + .height = YSIZE_PHYS +}; + static void ili9341_delay_ms(rt_uint32_t nms) { rt_thread_mdelay(nms); @@ -92,7 +101,11 @@ static rt_err_t ili9341_lcd_init(rt_device_t dev) ili9341_send_cmd_parameter(0x86); ili9341_send_cmd(0x36); - ili9341_send_cmd_parameter(0x48); // for 240x320 + + if (g_Ili9341Info.width == 240) + ili9341_send_cmd_parameter(0x48); // for 240x320 + else + ili9341_send_cmd_parameter(0xE8); // for 320x240 ili9341_send_cmd(0x3A); ili9341_send_cmd_parameter(0x55); @@ -157,14 +170,37 @@ static rt_err_t ili9341_lcd_init(rt_device_t dev) return RT_EOK; } -static void ili9341_fillscreen(uint16_t color) +#if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) +static void ili9341_fillrect(uint16_t *pixels, struct rt_device_rect_info *pRectInfo) +{ + ili9341_set_column(pRectInfo->x, pRectInfo->x + pRectInfo->width); + ili9341_set_page(pRectInfo->y, pRectInfo->y + pRectInfo->height); + ili9341_send_cmd(0x2c); + + ili9341_send_pixels(pixels, pRectInfo->height * pRectInfo->width * 2); +} +#endif + +static void ili9341_fillscreen(rt_uint16_t color) { +#if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) + struct rt_device_rect_info rectinfo = { 0, 0, XSIZE_PHYS, YSIZE_PHYS }; + int pixel_count = XSIZE_PHYS * YSIZE_PHYS; + rt_uint16_t *pu16ShadowBuf = (rt_uint16_t *)g_Ili9341Info.framebuffer; + + while (pixel_count--) + { + *pu16ShadowBuf++ = color; + } + ili9341_fillrect((uint16_t *)g_Ili9341Info.framebuffer, &rectinfo); +#else ili9341_set_column(0, (XSIZE_PHYS - 1)); ili9341_set_page(0, (YSIZE_PHYS - 1)); ili9341_send_cmd(0x2c); for (int i = 0; i < (XSIZE_PHYS * YSIZE_PHYS); i++) ili9341_send_pixel_data(color); +#endif } static void ili9341_lcd_set_pixel(const char *color, int x, int y) @@ -227,19 +263,20 @@ static rt_err_t ili9341_lcd_control(rt_device_t dev, int cmd, void *args) info = (struct rt_device_graphic_info *) args; RT_ASSERT(info != RT_NULL); - - info->bits_per_pixel = 16; - info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; - info->framebuffer = RT_NULL; - info->width = XSIZE_PHYS; - info->height = YSIZE_PHYS; + rt_memcpy(args, (void *)&g_Ili9341Info, sizeof(struct rt_device_graphic_info)); } break; case RTGRAPHIC_CTRL_RECT_UPDATE: + { +#if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) + RT_ASSERT(args != RT_NULL); + ili9341_fillrect((uint16_t *)g_Ili9341Info.framebuffer, (struct rt_device_rect_info *) args); +#else /* nothong to be done */ - break; - +#endif + } + break; default: break; } @@ -272,6 +309,11 @@ int rt_hw_lcd_ili9341_init(void) lcd_device.user_data = &ili9341_ops; +#if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) + g_Ili9341Info.framebuffer = rt_malloc_align(g_Ili9341Info.bits_per_pixel / 2 * g_Ili9341Info.height * g_Ili9341Info.width, 32); + RT_ASSERT(g_Ili9341Info.framebuffer != RT_NULL); +#endif + /* register graphic device driver */ rt_device_register(&lcd_device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.h b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.h index 3cc39cfcf1..3193d63da4 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.h +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.h @@ -28,8 +28,13 @@ // // Physical display size // -#define XSIZE_PHYS 240 -#define YSIZE_PHYS 320 +#if defined(NU_PKG_ILI9341_HORIZONTAL) + #define XSIZE_PHYS 320 + #define YSIZE_PHYS 240 +#else + #define XSIZE_PHYS 240 + #define YSIZE_PHYS 320 +#endif int rt_hw_lcd_ili9341_init(void); void ili9341_send_cmd(rt_uint8_t cmd); @@ -38,6 +43,7 @@ void ili9341_set_column(rt_uint16_t StartCol, rt_uint16_t EndCol); void ili9341_set_page(rt_uint16_t StartPage, rt_uint16_t EndPage); void ili9341_send_pixel_data(rt_uint16_t color); void ili9341_lcd_get_pixel(char *color, int x, int y); +void ili9341_send_pixels(rt_uint16_t *pixels, int len); #if defined(NU_PKG_USING_ILI9341_SPI) rt_err_t rt_hw_lcd_ili9341_spi_init(const char *spibusname); diff --git a/bsp/nuvoton/libraries/nu_packages/Kconfig b/bsp/nuvoton/libraries/nu_packages/Kconfig index 37c1bf6bdd..d1e47c6a60 100644 --- a/bsp/nuvoton/libraries/nu_packages/Kconfig +++ b/bsp/nuvoton/libraries/nu_packages/Kconfig @@ -47,6 +47,14 @@ menu "Nuvoton Packages Config" Choose this option if you the ili9341 device is with EBI interface. endchoice + config NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER + bool "Create an offscreen framebuffer." + default n + + config NU_PKG_ILI9341_HORIZONTAL + bool "Set horizontal view. (320x240)" + default n + endif endmenu diff --git a/bsp/nuvoton/libraries/nu_packages/NuUtils/inc/nu_bitutil.h b/bsp/nuvoton/libraries/nu_packages/NuUtils/inc/nu_bitutil.h index 2596ac0985..e74ad35094 100644 --- a/bsp/nuvoton/libraries/nu_packages/NuUtils/inc/nu_bitutil.h +++ b/bsp/nuvoton/libraries/nu_packages/NuUtils/inc/nu_bitutil.h @@ -43,7 +43,7 @@ extern "C" { */ __STATIC_INLINE int nu_clz(uint32_t x) { - return __CLZ(x); + return x ? __CLZ(x):32; } /* Count Leading Ones in word - Find Highest Zero @@ -65,7 +65,9 @@ __STATIC_INLINE int nu_clo(uint32_t x) */ __STATIC_INLINE int nu_ctz(uint32_t x) { - int c = __CLZ(x & -x); + int c = 32; + if (x) + c = __CLZ(x & -x); return x ? 31 - c : c; } diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h new file mode 100644 index 0000000000..5e7fff0327 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h @@ -0,0 +1,47 @@ +/**************************************************************************//** + * @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 "nuc980.h" +#include "nu_adc.h" +#include "nu_uart.h" +#include "nu_spi.h" +#include "nu_qspi.h" +#include "nu_i2c.h" +#include "nu_pdma.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_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/nuc980/Driver/Include/emac_reg.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/emac_reg.h new file mode 100644 index 0000000000..f9ad5efceb --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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/nuc980/Driver/Include/nu_adc.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h new file mode 100644 index 0000000000..341e2606f0 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h @@ -0,0 +1,110 @@ +/**************************************************************************//** +* @file adc.h +* @version V1.00 +* $Revision: 6 $ +* $Date: 15/10/05 7:00p $ +* @brief NUC980 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 + @{ +*/ + +#define ADC_ERR_ARGS 1 /*!< The arguments is wrong */ +#define ADC_ERR_CMD 2 /*!< The command is wrong */ + +/// @cond HIDDEN_SYMBOLS +typedef INT32(*ADC_CALLBACK)(UINT32 status, UINT32 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_MST 0x00000100 /*!< Menu Start Conversion */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ADC_CONF constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_CONF_NACEN 0x00000004 /*!< Normal AD Conversion Enable */ +#define ADC_CONF_SELFTEN 0x00000400 /*!< Selft Test Enable */ +#define ADC_CONF_HSPEED (1<<22) /*!< High Speed Enable */ + +#define ADC_CONF_CHSEL_Pos 12 /*!< Channel Selection Position */ +#define ADC_CONF_CHSEL_Msk (0xF<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/nuc980/Driver/Include/nu_cap.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_cap.h new file mode 100644 index 0000000000..f15142cf56 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_cap.h @@ -0,0 +1,471 @@ +/**************************************************************************//** + * @file cap.h + * @brief Image Capture Driver Header File + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef __NU_CAP_H__ +#define __NU_CAP_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 */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*---------------------- Capture Engine -------------------------*/ +/** + @addtogroup CAP Capture Engine(CAP) + Memory Mapped Structure for CAP Controller +@{ */ + +typedef struct +{ + __IO uint32_t CTL; + __IO uint32_t PAR; + __IO uint32_t INT; + __IO uint32_t POSTERIZE; + __IO uint32_t MD; + __IO uint32_t MDADDR; + __IO uint32_t MDYADDR; + __IO uint32_t SEPIA; + __IO uint32_t CWSP; + __IO uint32_t CWS; + __IO uint32_t PKTSL; + __IO uint32_t PLNSL; + __IO uint32_t FRCTL; + __IO uint32_t STRIDE; + /// @cond HIDDEN_SYMBOLS + uint32_t RESERVE0[1]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t FIFOTH; + __IO uint32_t CMPADDR; + /// @cond HIDDEN_SYMBOLS + uint32_t RESERVE1[1]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t PKTSM; + __IO uint32_t PLNSM; + __I uint32_t CURADDRP; + __I uint32_t CURADDRY; + __I uint32_t CURADDRU; + __I uint32_t CURVADDR; + __IO uint32_t PKTBA0; + __IO uint32_t PKTBA1; + /// @cond HIDDEN_SYMBOLS + uint32_t RESERVE2[6]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t YBA; + __IO uint32_t UBA; + __IO uint32_t VBA; + +} CAP_T; + +/** + @addtogroup CAP_CONST CAP Bit Field Definition + Constant Definitions for CAP Controller +@{ */ + +#define CAP_CTL_CAPEN_Pos (0) /*!< CAP_T::CTL: CAPEN Position */ +#define CAP_CTL_CAPEN_Msk (0x1ul << CAP_CTL_CAPEN_Pos) /*!< CAP_T::CTL: CAPEN Mask */ + +#define CAP_CTL_ADDRSW_Pos (3) /*!< CAP_T::CTL: ADDRSW Position */ +#define CAP_CTL_ADDRSW_Msk (0x1ul << CAP_CTL_ADDRSW_Pos) /*!< CAP_T::CTL: ADDRSW Mask */ + +#define CAP_CTL_PLNEN_Pos (5) /*!< CAP_T::CTL: PLNEN Position */ +#define CAP_CTL_PLNEN_Msk (0x1ul << CAP_CTL_PLNEN_Pos) /*!< CAP_T::CTL: PLNEN Mask */ + +#define CAP_CTL_PKTEN_Pos (6) /*!< CAP_T::CTL: PKTEN Position */ +#define CAP_CTL_PKTEN_Msk (0x1ul << CAP_CTL_PKTEN_Pos) /*!< CAP_T::CTL: PKTEN Mask */ + +#define CAP_CTL_SHUTTER_Pos (16) /*!< CAP_T::CTL: SHUTTER Position */ +#define CAP_CTL_SHUTTER_Msk (0x1ul << CAP_CTL_SHUTTER_Pos) /*!< CAP_T::CTL: SHUTTER Mask */ + +#define CAP_CTL_UPDATE_Pos (20) /*!< CAP_T::CTL: UPDATE Position */ +#define CAP_CTL_UPDATE_Msk (0x1ul << CAP_CTL_UPDATE_Pos) /*!< CAP_T::CTL: UPDATE Mask */ + +#define CAP_CTL_VPRST_Pos (24) /*!< CAP_T::CTL: VPRST Position */ +#define CAP_CTL_VPRST_Msk (0x1ul << CAP_CTL_VPRST_Pos) /*!< CAP_T::CTL: VPRST Mask */ + +#define CAP_PAR_INFMT_Pos (0) /*!< CAP_T::PAR: INFMT Position */ +#define CAP_PAR_INFMT_Msk (0x1ul << CAP_PAR_INFMT_Pos) /*!< CAP_T::PAR: INFMT Mask */ + +#define CAP_PAR_SENTYPE_Pos (1) /*!< CAP_T::PAR: SENTYPE Position */ +#define CAP_PAR_SENTYPE_Msk (0x1ul << CAP_PAR_SENTYPE_Pos) /*!< CAP_T::PAR: SENTYPE Mask */ + +#define CAP_PAR_INDATORD_Pos (2) /*!< CAP_T::PAR: INDATORD Position */ +#define CAP_PAR_INDATORD_Msk (0x3ul << CAP_PAR_INDATORD_Pos) /*!< CAP_T::PAR: INDATORD Mask */ + +#define CAP_PAR_OUTFMT_Pos (4) /*!< CAP_T::PAR: OUTFMT Position */ +#define CAP_PAR_OUTFMT_Msk (0x3ul << CAP_PAR_OUTFMT_Pos) /*!< CAP_T::PAR: OUTFMT Mask */ + +#define CAP_PAR_RANGE_Pos (6) /*!< CAP_T::PAR: RANGE Position */ +#define CAP_PAR_RANGE_Msk (0x1ul << CAP_PAR_RANGE_Pos) /*!< CAP_T::PAR: RANGE Mask */ + +#define CAP_PAR_PLNFMT_Pos (7) /*!< CAP_T::PAR: PLNFMT Position */ +#define CAP_PAR_PLNFMT_Msk (0x1ul << CAP_PAR_PLNFMT_Pos) /*!< CAP_T::PAR: PLNFMT Mask */ + +#define CAP_PAR_PCLKP_Pos (8) /*!< CAP_T::PAR: PCLKP Position */ +#define CAP_PAR_PCLKP_Msk (0x1ul << CAP_PAR_PCLKP_Pos) /*!< CAP_T::PAR: PCLKP Mask */ + +#define CAP_PAR_HSP_Pos (9) /*!< CAP_T::PAR: HSP Position */ +#define CAP_PAR_HSP_Msk (0x1ul << CAP_PAR_HSP_Pos) /*!< CAP_T::PAR: HSP Mask */ + +#define CAP_PAR_VSP_Pos (10) /*!< CAP_T::PAR: VSP Position */ +#define CAP_PAR_VSP_Msk (0x1ul << CAP_PAR_VSP_Pos) /*!< CAP_T::PAR: VSP Mask */ + +#define CAP_PAR_COLORCTL_Pos (11) /*!< CAP_T::PAR: COLORCTL Position */ +#define CAP_PAR_COLORCTL_Msk (0x3ul << CAP_PAR_COLORCTL_Pos) /*!< CAP_T::PAR: COLORCTL Mask */ + +#define CAP_PAR_FBB_Pos (18) /*!< CAP_T::PAR: FBB Position */ +#define CAP_PAR_FBB_Msk (0x1ul << CAP_PAR_FBB_Pos) /*!< CAP_T::PAR: FBB Mask */ + +#define CAP_INT_VINTF_Pos (0) /*!< CAP_T::INT: VINTF Position */ +#define CAP_INT_VINTF_Msk (0x1ul << CAP_INT_VINTF_Pos) /*!< CAP_T::INT: VINTF Mask */ + +#define CAP_INT_MEINTF_Pos (1) /*!< CAP_T::INT: MEINTF Position */ +#define CAP_INT_MEINTF_Msk (0x1ul << CAP_INT_MEINTF_Pos) /*!< CAP_T::INT: MEINTF Mask */ + +#define CAP_INT_ADDRMINTF_Pos (3) /*!< CAP_T::INT: ADDRMINTF Position */ +#define CAP_INT_ADDRMINTF_Msk (0x1ul << CAP_INT_ADDRMINTF_Pos) /*!< CAP_T::INT: ADDRMINTF Mask */ + +#define CAP_INT_MDINTF_Pos (4) /*!< CAP_T::INT: MDINTF Position */ +#define CAP_INT_MDINTF_Msk (0x1ul << CAP_INT_MDINTF_Pos) /*!< CAP_T::INT: MDINTF Mask */ + +#define CAP_INT_VIEN_Pos (16) /*!< CAP_T::INT: VIEN Position */ +#define CAP_INT_VIEN_Msk (0x1ul << CAP_INT_VIEN_Pos) /*!< CAP_T::INT: VIEN Mask */ + +#define CAP_INT_MEIEN_Pos (17) /*!< CAP_T::INT: MEIEN Position */ +#define CAP_INT_MEIEN_Msk (0x1ul << CAP_INT_MEIEN_Pos) /*!< CAP_T::INT: MEIEN Mask */ + +#define CAP_INT_ADDRMIEN_Pos (19) /*!< CAP_T::INT: ADDRMIEN Position */ +#define CAP_INT_ADDRMIEN_Msk (0x1ul << CAP_INT_ADDRMIEN_Pos) /*!< CAP_T::INT: ADDRMIEN Mask */ + +#define CAP_INT_MDIEN_Pos (20) /*!< CAP_T::INT: MDIEN Position */ +#define CAP_INT_MDIEN_Msk (0x1ul << CAP_INT_MDIEN_Pos) /*!< CAP_T::INT: MDIEN Mask */ + +#define CAP_POSTERIZE_VCOMP_Pos (0) /*!< CAP_T::POSTERIZE: VCOMP Position */ +#define CAP_POSTERIZE_VCOMP_Msk (0xfful << CAP_POSTERIZE_VCOMP_Pos) /*!< CAP_T::POSTERIZE: VCOMP Mask */ + +#define CAP_POSTERIZE_UCOMP_Pos (8) /*!< CAP_T::POSTERIZE: UCOMP Position */ +#define CAP_POSTERIZE_UCOMP_Msk (0xfful << CAP_POSTERIZE_UCOMP_Pos) /*!< CAP_T::POSTERIZE: UCOMP Mask */ + +#define CAP_POSTERIZE_YCOMP_Pos (16) /*!< CAP_T::POSTERIZE: YCOMP Position */ +#define CAP_POSTERIZE_YCOMP_Msk (0xfful << CAP_POSTERIZE_YCOMP_Pos) /*!< CAP_T::POSTERIZE: YCOMP Mask */ + +#define CAP_MD_MDEN_Pos (0) /*!< CAP_T::MD: MDEN Position */ +#define CAP_MD_MDEN_Msk (0x1ul << CAP_MD_MDEN_Pos) /*!< CAP_T::MD: MDEN Mask */ + +#define CAP_MD_MDBS_Pos (8) /*!< CAP_T::MD: MDBS Position */ +#define CAP_MD_MDBS_Msk (0x1ul << CAP_MD_MDBS_Pos) /*!< CAP_T::MD: MDBS Mask */ + +#define CAP_MD_MDSM_Pos (9) /*!< CAP_T::MD: MDSM Position */ +#define CAP_MD_MDSM_Msk (0x1ul << CAP_MD_MDSM_Pos) /*!< CAP_T::MD: MDSM Mask */ + +#define CAP_MD_MDDF_Pos (10) /*!< CAP_T::MD: MDDF Position */ +#define CAP_MD_MDDF_Msk (0x3ul << CAP_MD_MDDF_Pos) /*!< CAP_T::MD: MDDF Mask */ + +#define CAP_MD_MDTHR_Pos (16) /*!< CAP_T::MD: MDTHR Position */ +#define CAP_MD_MDTHR_Msk (0x1ful << CAP_MD_MDTHR_Pos) /*!< CAP_T::MD: MDTHR Mask */ + +#define CAP_MDADDR_MDADDR_Pos (0) /*!< CAP_T::MDADDR: MDADDR Position */ +#define CAP_MDADDR_MDADDR_Msk (0xfffffffful << CAP_MDADDR_MDADDR_Pos) /*!< CAP_T::MDADDR: MDADDR Mask */ + +#define CAP_MDYADDR_MDYADDR_Pos (0) /*!< CAP_T::MDYADDR: MDYADDR Position */ +#define CAP_MDYADDR_MDYADDR_Msk (0xfffffffful << CAP_MDYADDR_MDYADDR_Pos) /*!< CAP_T::MDYADDR: MDYADDR Mask */ + +#define CAP_SEPIA_VCOMP_Pos (0) /*!< CAP_T::SEPIA: VCOMP Position */ +#define CAP_SEPIA_VCOMP_Msk (0xfful << CAP_SEPIA_VCOMP_Pos) /*!< CAP_T::SEPIA: VCOMP Mask */ + +#define CAP_SEPIA_UCOMP_Pos (8) /*!< CAP_T::SEPIA: UCOMP Position */ +#define CAP_SEPIA_UCOMP_Msk (0xfful << CAP_SEPIA_UCOMP_Pos) /*!< CAP_T::SEPIA: UCOMP Mask */ + +#define CAP_CWSP_CWSADDRH_Pos (0) /*!< CAP_T::CWSP: CWSADDRH Position */ +#define CAP_CWSP_CWSADDRH_Msk (0xffful << CAP_CWSP_CWSADDRH_Pos) /*!< CAP_T::CWSP: CWSADDRH Mask */ + +#define CAP_CWSP_CWSADDRV_Pos (16) /*!< CAP_T::CWSP: CWSADDRV Position */ +#define CAP_CWSP_CWSADDRV_Msk (0x7fful << CAP_CWSP_CWSADDRV_Pos) /*!< CAP_T::CWSP: CWSADDRV Mask */ + +#define CAP_CWS_CWW_Pos (0) /*!< CAP_T::CWS: CWW Position */ +#define CAP_CWS_CWW_Msk (0xffful << CAP_CWS_CWW_Pos) /*!< CAP_T::CWS: CWW Mask */ + +#define CAP_CWS_CWH_Pos (16) /*!< CAP_T::CWS: CIWH Position */ +#define CAP_CWS_CWH_Msk (0x7fful << CAP_CWS_CWH_Pos) /*!< CAP_T::CWS: CIWH Mask */ + +#define CAP_PKTSL_PKTSHML_Pos (0) /*!< CAP_T::PKTSL: PKTSHML Position */ +#define CAP_PKTSL_PKTSHML_Msk (0xfful << CAP_PKTSL_PKTSHML_Pos) /*!< CAP_T::PKTSL: PKTSHML Mask */ + +#define CAP_PKTSL_PKTSHNL_Pos (8) /*!< CAP_T::PKTSL: PKTSHNL Position */ +#define CAP_PKTSL_PKTSHNL_Msk (0xfful << CAP_PKTSL_PKTSHNL_Pos) /*!< CAP_T::PKTSL: PKTSHNL Mask */ + +#define CAP_PKTSL_PKTSVML_Pos (16) /*!< CAP_T::PKTSL: PKTSVML Position */ +#define CAP_PKTSL_PKTSVML_Msk (0xfful << CAP_PKTSL_PKTSVML_Pos) /*!< CAP_T::PKTSL: PKTSVML Mask */ + +#define CAP_PKTSL_PKTSVNL_Pos (24) /*!< CAP_T::PKTSL: PKTSVNL Position */ +#define CAP_PKTSL_PKTSVNL_Msk (0xfful << CAP_PKTSL_PKTSVNL_Pos) /*!< CAP_T::PKTSL: PKTSVNL Mask */ + +#define CAP_PLNSL_PLNSHML_Pos (0) /*!< CAP_T::PLNSL: PLNSHML Position */ +#define CAP_PLNSL_PLNSHML_Msk (0xfful << CAP_PLNSL_PLNSHML_Pos) /*!< CAP_T::PLNSL: PLNSHML Mask */ + +#define CAP_PLNSL_PLNSHNL_Pos (8) /*!< CAP_T::PLNSL: PLNSHNL Position */ +#define CAP_PLNSL_PLNSHNL_Msk (0xfful << CAP_PLNSL_PLNSHNL_Pos) /*!< CAP_T::PLNSL: PLNSHNL Mask */ + +#define CAP_PLNSL_PLNSVML_Pos (16) /*!< CAP_T::PLNSL: PLNSVML Position */ +#define CAP_PLNSL_PLNSVML_Msk (0xfful << CAP_PLNSL_PLNSVML_Pos) /*!< CAP_T::PLNSL: PLNSVML Mask */ + +#define CAP_PLNSL_PLNSVNL_Pos (24) /*!< CAP_T::PLNSL: PLNSVNL Position */ +#define CAP_PLNSL_PLNSVNL_Msk (0xfful << CAP_PLNSL_PLNSVNL_Pos) /*!< CAP_T::PLNSL: PLNSVNL Mask */ + +#define CAP_FRCTL_FRM_Pos (0) /*!< CAP_T::FRCTL: FRM Position */ +#define CAP_FRCTL_FRM_Msk (0x3ful << CAP_FRCTL_FRM_Pos) /*!< CAP_T::FRCTL: FRM Mask */ + +#define CAP_FRCTL_FRN_Pos (8) /*!< CAP_T::FRCTL: FRN Position */ +#define CAP_FRCTL_FRN_Msk (0x3ful << CAP_FRCTL_FRN_Pos) /*!< CAP_T::FRCTL: FRN Mask */ + +#define CAP_STRIDE_PKTSTRIDE_Pos (0) /*!< CAP_T::STRIDE: PKTSTRIDE Position */ +#define CAP_STRIDE_PKTSTRIDE_Msk (0x3ffful << CAP_STRIDE_PKTSTRIDE_Pos) /*!< CAP_T::STRIDE: PKTSTRIDE Mask */ + +#define CAP_STRIDE_PLNSTRIDE_Pos (16) /*!< CAP_T::STRIDE: PLNSTRIDE Position */ +#define CAP_STRIDE_PLNSTRIDE_Msk (0x3ffful << CAP_STRIDE_PLNSTRIDE_Pos) /*!< CAP_T::STRIDE: PLNSTRIDE Mask */ + +#define CAP_FIFOTH_PLNVFTH_Pos (0) /*!< CAP_T::FIFOTH: PLNVFTH Position */ +#define CAP_FIFOTH_PLNVFTH_Msk (0xful << CAP_FIFOTH_PLNVFTH_Pos) /*!< CAP_T::FIFOTH: PLNVFTH Mask */ + +#define CAP_FIFOTH_PLNUFTH_Pos (8) /*!< CAP_T::FIFOTH: PLNUFTH Position */ +#define CAP_FIFOTH_PLNUFTH_Msk (0xful << CAP_FIFOTH_PLNUFTH_Pos) /*!< CAP_T::FIFOTH: PLNUFTH Mask */ + +#define CAP_FIFOTH_PLNYFTH_Pos (16) /*!< CAP_T::FIFOTH: PLNYFTH Position */ +#define CAP_FIFOTH_PLNYFTH_Msk (0x1ful << CAP_FIFOTH_PLNYFTH_Pos) /*!< CAP_T::FIFOTH: PLNYFTH Mask */ + +#define CAP_FIFOTH_PKTFTH_Pos (24) /*!< CAP_T::FIFOTH: PKTFTH Position */ +#define CAP_FIFOTH_PKTFTH_Msk (0x1ful << CAP_FIFOTH_PKTFTH_Pos) /*!< CAP_T::FIFOTH: PKTFTH Mask */ + +#define CAP_FIFOTH_OVF_Pos (31) /*!< CAP_T::FIFOTH: OVF Position */ +#define CAP_FIFOTH_OVF_Msk (0x1ul << CAP_FIFOTH_OVF_Pos) /*!< CAP_T::FIFOTH: OVF Mask */ + +#define CAP_CMPADDR_CMPADDR_Pos (0) /*!< CAP_T::CMPADDR: CMPADDR Position */ +#define CAP_CMPADDR_CMPADDR_Msk (0xfffffffful << CAP_CMPADDR_CMPADDR_Pos) /*!< CAP_T::CMPADDR: CMPADDR Mask */ + +#define CAP_PKTSM_PKTSHMH_Pos (0) /*!< CAP_T::PKTSM: PKTSHMH Position */ +#define CAP_PKTSM_PKTSHMH_Msk (0xfful << CAP_PKTSM_PKTSHMH_Pos) /*!< CAP_T::PKTSM: PKTSHMH Mask */ + +#define CAP_PKTSM_PKTSHNH_Pos (8) /*!< CAP_T::PKTSM: PKTSHNH Position */ +#define CAP_PKTSM_PKTSHNH_Msk (0xfful << CAP_PKTSM_PKTSHNH_Pos) /*!< CAP_T::PKTSM: PKTSHNH Mask */ + +#define CAP_PKTSM_PKTSVMH_Pos (16) /*!< CAP_T::PKTSM: PKTSVMH Position */ +#define CAP_PKTSM_PKTSVMH_Msk (0xfful << CAP_PKTSM_PKTSVMH_Pos) /*!< CAP_T::PKTSM: PKTSVMH Mask */ + +#define CAP_PKTSM_PKTSVNH_Pos (24) /*!< CAP_T::PKTSM: PKTSVNH Position */ +#define CAP_PKTSM_PKTSVNH_Msk (0xfful << CAP_PKTSM_PKTSVNH_Pos) /*!< CAP_T::PKTSM: PKTSVNH Mask */ + +#define CAP_PLNSM_PLNSHMH_Pos (0) /*!< CAP_T::PLNSM: PLNSHMH Position */ +#define CAP_PLNSM_PLNSHMH_Msk (0xfful << CAP_PLNSM_PLNSHMH_Pos) /*!< CAP_T::PLNSM: PLNSHMH Mask */ + +#define CAP_PLNSM_PLNSHNH_Pos (8) /*!< CAP_T::PLNSM: PLNSHNH Position */ +#define CAP_PLNSM_PLNSHNH_Msk (0xfful << CAP_PLNSM_PLNSHNH_Pos) /*!< CAP_T::PLNSM: PLNSHNH Mask */ + +#define CAP_PLNSM_PLNSVMH_Pos (16) /*!< CAP_T::PLNSM: PLNSVMH Position */ +#define CAP_PLNSM_PLNSVMH_Msk (0xfful << CAP_PLNSM_PLNSVMH_Pos) /*!< CAP_T::PLNSM: PLNSVMH Mask */ + +#define CAP_PLNSM_PLNSVNH_Pos (24) /*!< CAP_T::PLNSM: PLNSVNH Position */ +#define CAP_PLNSM_PLNSVNH_Msk (0xfful << CAP_PLNSM_PLNSVNH_Pos) /*!< CAP_T::PLNSM: PLNSVNH Mask */ + +#define CAP_CURADDRP_CURADDR_Pos (0) /*!< CAP_T::CURADDRP: CURADDR Position */ +#define CAP_CURADDRP_CURADDR_Msk (0xfffffffful << CAP_CURADDRP_CURADDR_Pos) /*!< CAP_T::CURADDRP: CURADDR Mask */ + +#define CAP_CURADDRY_CURADDR_Pos (0) /*!< CAP_T::CURADDRY: CURADDR Position */ +#define CAP_CURADDRY_CURADDR_Msk (0xfffffffful << CAP_CURADDRY_CURADDR_Pos) /*!< CAP_T::CURADDRY: CURADDR Mask */ + +#define CAP_CURADDRU_CURADDR_Pos (0) /*!< CAP_T::CURADDRU: CURADDR Position */ +#define CAP_CURADDRU_CURADDR_Msk (0xfffffffful << CAP_CURADDRU_CURADDR_Pos) /*!< CAP_T::CURADDRU: CURADDR Mask */ + +#define CAP_CURVADDR_CURADDR_Pos (0) /*!< CAP_T::CURVADDR: CURADDR Position */ +#define CAP_CURVADDR_CURADDR_Msk (0xfffffffful << CAP_CURVADDR_CURADDR_Pos) /*!< CAP_T::CURVADDR: CURADDR Mask */ + +#define CAP_PKTBA0_BASEADDR_Pos (0) /*!< CAP_T::PKTBA0: BASEADDR Position */ +#define CAP_PKTBA0_BASEADDR_Msk (0xfffffffful << CAP_PKTBA0_BASEADDR_Pos) /*!< CAP_T::PKTBA0: BASEADDR Mask */ + +#define CAP_PKTBA1_BASEADDR_Pos (0) /*!< CAP_T::PKTBA1: BASEADDR Position */ +#define CAP_PKTBA1_BASEADDR_Msk (0xfffffffful << CAP_PKTBA1_BASEADDR_Pos) /*!< CAP_T::PKTBA1: BASEADDR Mask */ + +#define CAP_YBA_BASEADDR_Pos (0) /*!< CAP_T::YBA: BASEADDR Position */ +#define CAP_YBA_BASEADDR_Msk (0xfffffffful << CAP_YBA_BASEADDR_Pos) /*!< CAP_T::YBA: BASEADDR Mask */ + +#define CAP_UBA_BASEADDR_Pos (0) /*!< CAP_T::UBA: BASEADDR Position */ +#define CAP_UBA_BASEADDR_Msk (0xfffffffful << CAP_UBA_BASEADDR_Pos) /*!< CAP_T::UBA: BASEADDR Mask */ + +#define CAP_VBA_BASEADDR_Pos (0) /*!< CAP_T::VBA: BASEADDR Position */ +#define CAP_VBA_BASEADDR_Msk (0xfffffffful << CAP_VBA_BASEADDR_Pos) /*!< CAP_T::VBA: BASEADDR Mask */ + +/**@}*/ /* CAP_CONST */ +/**@}*/ /* end of CAP register group */ + + +#define CAP0 ((CAP_T *) CAP0_BA) +#define CAP1 ((CAP_T *) CAP1_BA) + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CAP_Driver CAP Driver + @{ +*/ + +/** @addtogroup CAP_EXPORTED_CONSTANTS CAP Exported Constants + @{ +*/ + + + + +/*---------------------------------------------------------------------------------------------------------*/ +/* VINCTRL constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define CAP_CTL_CAPEN (1ul<CTL & CAP_CTL_CAPEN_Msk)?0:1) + +/** + * @brief Clear CAP flag + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32IntMask interrupt flags settings. It could be + * - \ref CAP_INT_VINTF_Msk + * - \ref CAP_INT_MEINTF_Msk + * - \ref CAP_INT_ADDRMINTF_Msk + * - \ref CAP_INT_MDINTF_Msk + * + * @return TRUE(Enable) or FALSE(Disable) + * + * @details Clear Image Capture Interface interrupt flag + * \hideinitializer + */ +#define CAP_CLR_INT_FLAG(VCAP,u32IntMask) (VCAP->INT |=u32IntMask) + +/** + * @brief Get CAP Interrupt status + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @return TRUE(Enable) or FALSE(Disable) + * + * @details Get Image Capture Interface interrupt status. + * \hideinitializer + */ +#define CAP_GET_INT_STS(VCAP) (VCAP->INT) + +void CAP_Open(CAP_T *VCAP, uint32_t u32InFormat, uint32_t u32OutFormet); +void CAP_SetCroppingWindow(CAP_T *VCAP, uint32_t u32VStart, uint32_t u32HStart, uint32_t u32Height, uint32_t u32Width); +void CAP_SetPacketBuf(CAP_T *VCAP, uint32_t u32Address); +void CAP_SetPlanarBuf(CAP_T *VCAP, uint32_t u32YAddr, uint32_t u32UAddr, uint32_t u32VAddr); +void CAP_Close(CAP_T *VCAP); +void CAP_EnableInt(CAP_T *VCAP, uint32_t u32IntMask); +void CAP_DisableInt(CAP_T *VCAP, uint32_t u32IntMask); +void CAP_Start(CAP_T *VCAP); +void CAP_Stop(CAP_T *VCAP, uint32_t u32FrameComplete); +void CAP_SetPacketScaling(CAP_T *VCAP, uint32_t u32VNumerator, uint32_t u32VDenominator, uint32_t u32HNumerator, uint32_t u32HDenominator); +void CAP_SetPlanarScaling(CAP_T *VCAP, uint32_t u32VNumerator, uint32_t u32VDenominator, uint32_t u32HNumerator, uint32_t u32HDenominator); +void CAP_SetPacketStride(CAP_T *VCAP, uint32_t u32Stride); +void CAP_SetPlanarStride(CAP_T *VCAP, uint32_t u32Stride); +void CAP_EnableMotionDet(CAP_T *VCAP, uint32_t u32Freq, uint32_t u32BlockSize, uint32_t u32Format, uint32_t u32Threshold, uint32_t u32YDetAddr, uint32_t u32DetAddr); +void CAP_DisableMotionDet(CAP_T *VCAP); + +/*@}*/ /* end of group CAP_EXPORTED_FUNCTIONS */ + + + +/*@}*/ /* end of group CAP_Driver */ + +/*@}*/ /* end of group Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__CAP_H__ + diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_crypto.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_crypto.h new file mode 100644 index 0000000000..cec2d6f187 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_crypto.h @@ -0,0 +1,1456 @@ +/**************************************************************************//** + * @file crypto.h + * @version V1.10 + * @brief Cryptographic Accelerator driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef __NU_CRYPTO_H__ +#define __NU_CRYPTO_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup Crypto_Driver Crypto Driver + @{ +*/ + +/** + @addtogroup CRPT Cryptographic Accelerator(CRPT) + Memory Mapped Structure for Cryptographic Accelerator +@{ */ + +typedef struct +{ + + /** + * @var CRPT_T::INTEN + * Offset: 0x00 Crypto Interrupt Enable Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |AESIEN |AES Interrupt Enable Control + * | | |0 = AES interrupt Disabled. + * | | |1 = AES interrupt Enabled. + * | | |In DMA mode, an interrupt will be triggered when amount of data set in AES_DMA_CNT is fed into the AES engine. + * | | |In Non-DMA mode, an interrupt will be triggered when the AES engine finishes the operation. + * |[1] |AESEIEN |AES Error Flag Enable Control + * | | |0 = AES error interrupt flag Disabled. + * | | |1 = AES error interrupt flag Enabled. + * |[8] |TDESIEN |TDES/DES Interrupt Enable Control + * | | |0 = TDES/DES interrupt Disabled. + * | | |1 = TDES/DES interrupt Enabled. + * | | |In DMA mode, an interrupt will be triggered when amount of data set in TDES_DMA_CNT is fed into the TDES engine. + * | | |In Non-DMA mode, an interrupt will be triggered when the TDES engine finishes the operation. + * |[9] |TDESEIEN |TDES/DES Error Flag Enable Control + * | | |0 = TDES/DES error interrupt flag Disabled. + * | | |1 = TDES/DES error interrupt flag Enabled. + * |[16] |PRNGIEN |PRNG Interrupt Enable Control + * | | |0 = PRNG interrupt Disabled. + * | | |1 = PRNG interrupt Enabled. + * |[22] |ECCIEN |ECC Interrupt Enable Control + * | | |0 = ECC interrupt Disabled. + * | | |1 = ECC interrupt Enabled. + * | | |In DMA mode, an interrupt will be triggered when amount of data set in ECC_DMA_CNT is fed into the ECC engine. + * | | |In Non-DMA mode, an interrupt will be triggered when the ECC engine finishes the operation. + * |[23] |ECCEIEN |ECC Error Interrupt Enable Control + * | | |0 = ECC error interrupt flag Disabled. + * | | |1 = ECC error interrupt flag Enabled. + * |[24] |HMACIEN |SHA/HMAC Interrupt Enable Control + * | | |0 = SHA/HMAC interrupt Disabled. + * | | |1 = SHA/HMAC interrupt Enabled. + * | | |In DMA mode, an interrupt will be triggered when amount of data set in SHA _DMA_CNT is fed into the SHA/HMAC engine + * | | |In Non-DMA mode, an interrupt will be triggered when the SHA/HMAC engine finishes the operation. + * |[25] |HMACEIEN |SHA/HMAC Error Interrupt Enable Control + * | | |0 = SHA/HMAC error interrupt flag Disabled. + * | | |1 = SHA/HMAC error interrupt flag Enabled. + * @var CRPT_T::INTSTS + * Offset: 0x04 Crypto Interrupt Flag + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |AESIF |AES Finish Interrupt Flag + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No AES interrupt. + * | | |= AES encryption/decryption done interrupt. + * |[1] |AESEIF |AES Error Flag + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No AES error. + * | | |1 = AES encryption/decryption done interrupt. + * |[8] |TDESIF |TDES/DES Finish Interrupt Flag + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No TDES/DES interrupt. + * | | |1 = TDES/DES encryption/decryption done interrupt. + * |[9] |TDESEIF |TDES/DES Error Flag + * | | |This bit includes the operating and setting error + * | | |The detailed flag is shown in the CRPT_TDES_STS register + * | | |This includes operating and setting error. + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No TDES/DES error. + * | | |1 = TDES/DES encryption/decryption error interrupt. + * |[16] |PRNGIF |PRNG Finish Interrupt Flag + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No PRNG interrupt. + * | | |1 = PRNG key generation done interrupt. + * |[22] |ECCIF |ECC Finish Interrupt Flag + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No ECC interrupt. + * | | |1 = ECC operation done interrupt. + * |[23] |ECCEIF |ECC Error Flag + * | | |This register includes operating and setting error. The detail flag is shown in CRPT_ECC_STS register. + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No ECC error. + * | | |1 = ECC error interrupt. + * |[24] |HMACIF |SHA/HMAC Finish Interrupt Flag + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No SHA/HMAC interrupt. + * | | |1 = SHA/HMAC operation done interrupt. + * |[25] |HMACEIF |SHA/HMAC Error Flag + * | | |This register includes operating and setting error. The detail flag is shown in CRPT_HMAC_STS register. + * | | |This bit is cleared by writing 1, and it has no effect by writing 0. + * | | |0 = No SHA/HMAC error. + * | | |1 = SHA/HMAC error interrupt. + * @var CRPT_T::PRNG_CTL + * Offset: 0x08 PRNG Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |START |Start PRNG Engine + * | | |0 = Stop PRNG engine. + * | | |1 = Generate new key and store the new key to register CRPT_PRNG_KEYx , which will be cleared when the new key is generated. + * |[1] |SEEDRLD |Reload New Seed for PRNG Engine + * | | |0 = Generating key based on the current seed. + * | | |1 = Reload new seed. + * |[3:2] |KEYSZ |PRNG Generate Key Size + * | | |00 = 64 bits. + * | | |01 = 128 bits. + * | | |10 = 192 bits. + * | | |11 = 256 bits. + * |[8] |BUSY |PRNG Busy (Read Only) + * | | |0 = PRNG engine is idle. + * | | |1 = Indicate that the PRNG engine is generating CRPT_PRNG_KEYx. + * @var CRPT_T::PRNG_SEED + * Offset: 0x0C Seed for PRNG + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SEED |Seed for PRNG (Write Only) + * | | |The bits store the seed for PRNG engine. + * @var CRPT_T::PRNG_KEY[8] + * Offset: 0x10 ~ 0x2C PRNG Generated Key0 ~ Key7 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |KEY |Store PRNG Generated Key (Read Only) + * | | |The bits store the key that is generated by PRNG. + * @var CRPT_T::AES_FDBCK[4] + * Offset: 0x50 ~ 0x5C AES Engine Output Feedback Data after Cryptographic Operation + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |FDBCK |AES Feedback Information + * | | |The feedback value is 128 bits in size. + * | | |The AES engine uses the data from CRPT_AES_FDBCKx as the data inputted to CRPT_AESn_IVx for the next block in DMA cascade mode. + * | | |The AES engine outputs feedback information for IV in the next block's operation + * | | |Software can use this feedback information to implement more than four DMA channels + * | | |Software can store that feedback value temporarily + * | | |After switching back, fill the stored feedback value to this register in the same channel operation, and then continue the operation with the original setting. + * @var CRPT_T::TDES_FDBCKH + * Offset: 0x60 TDES/DES Engine Output Feedback High Word Data after Cryptographic Operation + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |FDBCK |TDES/DES Feedback + * | | |The feedback value is 64 bits in size. + * | | |The TDES/DES engine uses the data from {CRPT_TDES_FDBCKH, CRPT_TDES_FDBCKL} as the data inputted to {CRPT_TDESn_IVH, CRPT_TDESn_IVL} for the next block in DMA cascade mode + * | | |The feedback register is for CBC, CFB, and OFB mode. + * | | |TDES/DES engine outputs feedback information for IV in the next block's operation + * | | |Software can use this feedback information to implement more than four DMA channels + * | | |Software can store that feedback value temporarily + * | | |After switching back, fill the stored feedback value to this register in the same channel operation + * | | |Then can continue the operation with the original setting. + * @var CRPT_T::TDES_FDBCKL + * Offset: 0x64 TDES/DES Engine Output Feedback Low Word Data after Cryptographic Operation + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |FDBCK |TDES/DES Feedback + * | | |The feedback value is 64 bits in size. + * | | |The TDES/DES engine uses the data from {CRPT_TDES_FDBCKH, CRPT_TDES_FDBCKL} as the data inputted to {CRPT_TDESn_IVH, CRPT_TDESn_IVL} for the next block in DMA cascade mode + * | | |The feedback register is for CBC, CFB, and OFB mode. + * | | |TDES/DES engine outputs feedback information for IV in the next block's operation + * | | |Software can use this feedback information to implement more than four DMA channels + * | | |Software can store that feedback value temporarily + * | | |After switching back, fill the stored feedback value to this register in the same channel operation + * | | |Then can continue the operation with the original setting. + * @var CRPT_T::AES_CTL + * Offset: 0x100 AES Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |START |AES Engine Start + * | | |0 = No effect. + * | | |1 = Start AES engine. BUSY flag will be set. + * | | |Note: This bit is always 0 when it's read back. + * |[1] |STOP |AES Engine Stop + * | | |0 = No effect. + * | | |1 = Stop AES engine. + * | | |Note: This bit is always 0 when it's read back. + * |[3:2] |KEYSZ |AES Key Size + * | | |This bit defines three different key size for AES operation. + * | | |2'b00 = 128 bits key. + * | | |2'b01 = 192 bits key. + * | | |2'b10 = 256 bits key. + * | | |2'b11 = Reserved. + * | | |If the AES accelerator is operating and the corresponding flag BUSY is 1, updating this register has no effect. + * |[5] |DMALAST |AES Last Block + * | | |In DMA mode, this bit must be set as beginning the last DMA cascade round. + * | | |In Non-DMA mode, this bit must be set when feeding in the last block of data in ECB, CBC, CTR, OFB, and CFB mode, and feeding in the (last-1) block of data at CBC-CS1, CBC-CS2, and CBC-CS3 mode. + * | | |This bit is always 0 when it's read back. Must be written again once START is triggered. + * |[6] |DMACSCAD |AES Engine DMA with Cascade Mode + * | | |0 = DMA cascade function Disabled. + * | | |1 = In DMA cascade mode, software can update DMA source address register, destination address register, and byte count register during a cascade operation, without finishing the accelerator operation. + * |[7] |DMAEN |AES Engine DMA Enable Control + * | | |0 = AES DMA engine Disabled. + * | | |The AES engine operates in Non-DMA mode, and gets data from the port CRPT_AES_DATIN. + * | | |1 = AES_DMA engine Enabled. + * | | |The AES engine operates in DMA mode, and data movement from/to the engine is done by DMA logic. + * |[15:8] |OPMODE |AES Engine Operation Modes + * | | |0x00 = ECB (Electronic Codebook Mode) 0x01 = CBC (Cipher Block Chaining Mode). + * | | |0x02 = CFB (Cipher Feedback Mode). + * | | |0x03 = OFB (Output Feedback Mode). + * | | |0x04 = CTR (Counter Mode). + * | | |0x10 = CBC-CS1 (CBC Ciphertext-Stealing 1 Mode). + * | | |0x11 = CBC-CS2 (CBC Ciphertext-Stealing 2 Mode). + * | | |0x12 = CBC-CS3 (CBC Ciphertext-Stealing 3 Mode). + * |[16] |ENCRPT |AES Encryption/Decryption + * | | |0 = AES engine executes decryption operation. + * | | |1 = AES engine executes encryption operation. + * |[22] |OUTSWAP |AES Engine Output Data Swap + * | | |0 = Keep the original order. + * | | |1 = The order that CPU outputs data from the accelerator will be changed from {byte3, byte2, byte1, byte0} to {byte0, byte1, byte2, byte3}. + * |[23] |INSWAP |AES Engine Input Data Swap + * | | |0 = Keep the original order. + * | | |1 = The order that CPU feeds data to the accelerator will be changed from {byte3, byte2, byte1, byte0} to {byte0, byte1, byte2, byte3}. + * |[25:24] |CHANNEL |AES Engine Working Channel + * | | |00 = Current control register setting is for channel 0. + * | | |01 = Current control register setting is for channel 1. + * | | |10 = Current control register setting is for channel 2. + * | | |11 = Current control register setting is for channel 3. + * |[30:26] |KEYUNPRT |Unprotect Key + * | | |Writing 0 to CRPT_AES_CTL[31] and "10110" to CRPT_AES_CTL[30:26] is to unprotect the AES key. + * | | |The KEYUNPRT can be read and written + * | | |When it is written as the AES engine is operating, BUSY flag is 1, there would be no effect on KEYUNPRT. + * |[31] |KEYPRT |Protect Key + * | | |Read as a flag to reflect KEYPRT. + * | | |0 = No effect. + * | | |1 = Protect the content of the AES key from reading + * | | |The return value for reading CRPT_AESn_KEYx is not the content of the registers CRPT_AESn_KEYx + * | | |Once it is set, it can be cleared by asserting KEYUNPRT + * | | |And the key content would be cleared as well. + * @var CRPT_T::AES_STS + * Offset: 0x104 AES Engine Flag + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSY |AES Engine Busy + * | | |0 = The AES engine is idle or finished. + * | | |1 = The AES engine is under processing. + * |[8] |INBUFEMPTY|AES Input Buffer Empty + * | | |0 = There are some data in input buffer waiting for the AES engine to process. + * | | |1 = AES input buffer is empty + * | | |Software needs to feed data to the AES engine + * | | |Otherwise, the AES engine will be pending to wait for input data. + * |[9] |INBUFFULL |AES Input Buffer Full Flag + * | | |0 = AES input buffer is not full. Software can feed the data into the AES engine. + * | | |1 = AES input buffer is full + * | | |Software cannot feed data to the AES engine + * | | |Otherwise, the flag INBUFERR will be set to 1. + * |[10] |INBUFERR |AES Input Buffer Error Flag + * | | |0 = No error. + * | | |1 = Error happens during feeding data to the AES engine. + * |[12] |CNTERR |CRPT_AESn_CNT Setting Error + * | | |0 = No error in CRPT_AESn_CNT setting. + * | | |1 = CRPT_AESn_CNT is not a multiply of 16 in ECB, CBC, CFB, OFB, and CTR mode. + * |[16] |OUTBUFEMPTY|AES Out Buffer Empty + * | | |0 = AES output buffer is not empty. There are some valid data kept in output buffer. + * | | |1 = AES output buffer is empty + * | | |Software cannot get data from CRPT_AES_DATOUT + * | | |Otherwise, the flag OUTBUFERR will be set to 1 since the output buffer is empty. + * |[17] |OUTBUFFULL|AES Out Buffer Full Flag + * | | |0 = AES output buffer is not full. + * | | |1 = AES output buffer is full, and software needs to get data from CRPT_AES_DATOUT + * | | |Otherwise, the AES engine will be pending since the output buffer is full. + * |[18] |OUTBUFERR |AES Out Buffer Error Flag + * | | |0 = No error. + * | | |1 = Error happens during getting the result from AES engine. + * |[20] |BUSERR |AES DMA Access Bus Error Flag + * | | |0 = No error. + * | | |1 = Bus error will stop DMA operation and AES engine. + * @var CRPT_T::AES_DATIN + * Offset: 0x108 AES Engine Data Input Port Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DATIN |AES Engine Input Port + * | | |CPU feeds data to AES engine through this port by checking CRPT_AES_STS. Feed data as INBUFFULL is 0. + * @var CRPT_T::AES_DATOUT + * Offset: 0x10C AES Engine Data Output Port Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DATOUT |AES Engine Output Port + * | | |CPU gets results from the AES engine through this port by checking CRPT_AES_STS + * | | |Get data as OUTBUFEMPTY is 0. + * @var CRPT_T::AES0_KEY[8] + * Offset: 0x110 ~ 0x12C AES Key Word 0 ~ 7 Register for Channel 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |KEY |CRPT_AESn_KEYx + * | | |The KEY keeps the security key for AES operation. + * | | |n = 0, 1..3. + * | | |x = 0, 1..7. + * | | |The security key for AES accelerator can be 128, 192, or 256 bits and four, six, or eight 32-bit registers are to store each security key + * | | |{CRPT_AESn_KEY3, CRPT_AESn_KEY2, CRPT_AESn_KEY1, CRPT_AESn_KEY0} stores the 128-bit security key for AES operation + * | | |{CRPT_AESn_KEY5, CRPT_AESn_KEY4, CRPT_AESn_KEY3, CRPT_AESn_KEY2, CRPT_AESn_KEY1, CRPT_AESn_KEY0} stores the 192-bit security key for AES operation + * | | |{CRPT_AESn_KEY7, CRPT_AESn_KEY6, CRPT_AESn_KEY5, CRPT_AESn_KEY4, CRPT_AESn_KEY3, CRPT_AESn_KEY2, CRPT_AESn_KEY1, CRPT_AESn_KEY0} stores the 256-bit security key for AES operation. + * @var CRPT_T::AES0_IV[4] + * Offset: 0x130 ~ 0x13C AES Initial Vector Word 0 ~ 3 Register for Channel 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |IV |AES Initial Vectors + * | | |n = 0, 1..3. + * | | |x = 0, 1..3. + * | | |Four initial vectors (CRPT_AESn_IV0, CRPT_AESn_IV1, CRPT_AESn_IV2, and CRPT_AESn_IV3) are for AES operating in CBC, CFB, and OFB mode + * | | |Four registers (CRPT_AESn_IV0, CRPT_AESn_IV1, CRPT_AESn_IV2, and CRPT_AESn_IV3) act as Nonce counter when the AES engine is operating in CTR mode. + * @var CRPT_T::AES0_SADDR + * Offset: 0x140 AES DMA Source Address Register for Channel 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SADDR |AES DMA Source Address + * | | |The AES accelerator supports DMA function to transfer the plain text between system memory and embedded FIFO + * | | |The SADDR keeps the source address of the data buffer where the source text is stored + * | | |Based on the source address, the AES accelerator can read the plain text from system memory and do AES operation + * | | |The start of source address should be located at word boundary + * | | |In other words, bit 1 and 0 of SADDR are ignored. + * | | |SADDR can be read and written + * | | |Writing to SADDR while the AES accelerator is operating doesn't affect the current AES operation + * | | |But the value of SADDR will be updated later on + * | | |Consequently, software can prepare the DMA source address for the next AES operation. + * | | |In DMA mode, software can update the next CRPT_AESn_SADDR before triggering START. + * | | |The value of CRPT_AESn_SADDR and CRPT_AESn_DADDR can be the same. + * @var CRPT_T::AES0_DADDR + * Offset: 0x144 AES DMA Destination Address Register for Channel 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DADDR |AES DMA Destination Address + * | | |The AES accelerator supports DMA function to transfer the cipher text between system memory and embedded FIFO + * | | |The DADDR keeps the destination address of the data buffer where the engine output's text will be stored + * | | |Based on the destination address, the AES accelerator can write the cipher text back to system memory after the AES operation is finished + * | | |The start of destination address should be located at word boundary + * | | |In other words, bit 1 and 0 of DADDR are ignored. + * | | |DADDR can be read and written + * | | |Writing to DADDR while the AES accelerator is operating doesn't affect the current AES operation + * | | |But the value of DADDR will be updated later on + * | | |Consequently, software can prepare the destination address for the next AES operation. + * | | |In DMA mode, software can update the next CRPT_AESn_DADDR before triggering START. + * | | |The value of CRPT_AESn_SADDR and CRPT_AESn_DADDR can be the same. + * @var CRPT_T::AES0_CNT + * Offset: 0x148 AES Byte Count Register for Channel 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CNT |AES Byte Count + * | | |The CRPT_AESn_CNT keeps the byte count of source text that is for the AES engine operating in DMA mode + * | | |The CRPT_AESn_CNT is 32-bit and the maximum of byte count is 4G bytes. + * | | |CRPT_AESn_CNT can be read and written + * | | |Writing to CRPT_AESn_CNT while the AES accelerator is operating doesn't affect the current AES operation + * | | |But the value of CRPT_AESn_CNT will be updated later on + * | | |Consequently, software can prepare the byte count of data for the next AES operation. + * | | |According to CBC-CS1, CBC-CS2, and CBC-CS3 standard, the count of operation data must be at least one block + * | | |Operations that are less than one block will output unexpected result. + * | | |In Non-DMA ECB, CBC, CFB, OFB, and CTR mode, CRPT_AESn_CNT must be set as byte count for the last block of data before feeding in the last block of data + * | | |In Non-DMA CBC-CS1, CBC-CS2, and CBC-CS3 mode, CRPT_AESn_CNT must be set as byte count for the last two blocks of data before feeding in the last two blocks of data. + * @var CRPT_T::HMAC_CTL + * Offset: 0x300 SHA/HMAC Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |START |SHA/HMAC Engine Start + * | | |0 = No effect. + * | | |1 = Start SHA/HMAC engine. BUSY flag will be set. + * | | |This bit is always 0 when it's read back. + * |[1] |STOP |SHA/HMAC Engine Stop + * | | |0 = No effect. + * | | |1 = Stop SHA/HMAC engine. + * | | |This bit is always 0 when it's read back. + * |[4] |HMACEN |HMAC_SHA Engine Operating Mode + * | | |0 = execute SHA function. + * | | |1 = execute HMAC function. + * |[5] |DMALAST |SHA/HMAC Last Block + * | | |This bit must be set as feeding in last byte of data. + * |[7] |DMAEN |SHA/HMAC Engine DMA Enable Control + * | | |0 = SHA/HMAC DMA engine Disabled. + * | | |SHA/HMAC engine operates in Non-DMA mode, and gets data from the port CRPT_HMAC_DATIN. + * | | |1 = SHA/HMAC DMA engine Enabled. + * | | |SHA/HMAC engine operates in DMA mode, and data movement from/to the engine is done by DMA logic. + * |[10:8] |OPMODE |SHA/HMAC Engine Operation Modes + * | | |0x0xx: SHA160 + * | | |0x100: SHA256 + * | | |0x101: SHA224 + * | | |0x110: SHA512 + * | | |0x111: SHA384 + * | | |These bits can be read and written. But writing to them wouldn't take effect as BUSY is 1. + * |[22] |OUTSWAP |SHA/HMAC Engine Output Data Swap + * | | |0 = Keep the original order. + * | | |1 = The order that CPU feeds data to the accelerator will be changed from {byte3, byte2, byte1, byte0} to {byte0, byte1, byte2, byte3}. + * |[23] |INSWAP |SHA/HMAC Engine Input Data Swap + * | | |0 = Keep the original order. + * | | |1 = The order that CPU feeds data to the accelerator will be changed from {byte3, byte2, byte1, byte0} to {byte0, byte1, byte2, byte3}. + * @var CRPT_T::HMAC_STS + * Offset: 0x304 SHA/HMAC Status Flag + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSY |SHA/HMAC Engine Busy + * | | |0 = SHA/HMAC engine is idle or finished. + * | | |1 = SHA/HMAC engine is busy. + * |[1] |DMABUSY |SHA/HMAC Engine DMA Busy Flag + * | | |0 = SHA/HMAC DMA engine is idle or finished. + * | | |1 = SHA/HMAC DMA engine is busy. + * |[8] |DMAERR |SHA/HMAC Engine DMA Error Flag + * | | |0 = Show the SHA/HMAC engine access normal. + * | | |1 = Show the SHA/HMAC engine access error. + * |[16] |DATINREQ |SHA/HMAC Non-DMA Mode Data Input Request + * | | |0 = No effect. + * | | |1 = Request SHA/HMAC Non-DMA mode data input. + * @var CRPT_T::HMAC_DGST[16] + * Offset: 0x308 ~ 0x344 SHA/HMAC Digest Message 0 ~ 15 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DGST |SHA/HMAC Digest Message Output Register + * | | |For SHA-160, the digest is stored in CRPT_HMAC_DGST0 ~ CRPT_HMAC_DGST4. + * | | |For SHA-224, the digest is stored in CRPT_HMAC_DGST0 ~ CRPT_HMAC_DGST6. + * | | |For SHA-256, the digest is stored in CRPT_HMAC_DGST0 ~ CRPT_HMAC_DGST7. + * | | |For SHA-384, the digest is stored in CRPT_HMAC_DGST0 ~ CRPT_HMAC_DGST11. + * | | |For SHA-512, the digest is stored in CRPT_HMAC_DGST0 ~ CRPT_HMAC_DGST15. + * @var CRPT_T::HMAC_KEYCNT + * Offset: 0x348 SHA/HMAC Key Byte Count Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |KEYCNT |SHA/HMAC Key Byte Count + * | | |The CRPT_HMAC_KEYCNT keeps the byte count of key that SHA/HMAC engine operates + * | | |The register is 32-bit and the maximum byte count is 4G bytes + * | | |It can be read and written. + * | | |Writing to the register CRPT_HMAC_KEYCNT as the SHA/HMAC accelerator operating doesn't affect the current SHA/HMAC operation + * | | |But the value of CRPT_SHA _KEYCNT will be updated later on + * | | |Consequently, software can prepare the key count for the next SHA/HMAC operation. + * @var CRPT_T::HMAC_SADDR + * Offset: 0x34C SHA/HMAC DMA Source Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SADDR |SHA/HMAC DMA Source Address + * | | |The SHA/HMAC accelerator supports DMA function to transfer the plain text between system memory and embedded FIFO + * | | |The CRPT_HMAC_SADDR keeps the source address of the data buffer where the source text is stored + * | | |Based on the source address, the SHA/HMAC accelerator can read the plain text from system memory and do SHA/HMAC operation + * | | |The start of source address should be located at word boundary + * | | |In other words, bit 1 and 0 of CRPT_HMAC_SADDR are ignored. + * | | |CRPT_HMAC_SADDR can be read and written + * | | |Writing to CRPT_HMAC_SADDR while the SHA/HMAC accelerator is operating doesn't affect the current SHA/HMAC operation + * | | |But the value of CRPT_HMAC_SADDR will be updated later on + * | | |Consequently, software can prepare the DMA source address for the next SHA/HMAC operation. + * | | |In DMA mode, software can update the next CRPT_HMAC_SADDR before triggering START. + * | | |CRPT_HMAC_SADDR and CRPT_HMAC_DADDR can be the same in the value. + * @var CRPT_T::HMAC_DMACNT + * Offset: 0x350 SHA/HMAC Byte Count Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DMACNT |SHA/HMAC Operation Byte Count + * | | |The CRPT_HMAC_DMACNT keeps the byte count of source text that is for the SHA/HMAC engine operating in DMA mode + * | | |The CRPT_HMAC_DMACNT is 32-bit and the maximum of byte count is 4G bytes. + * | | |CRPT_HMAC_DMACNT can be read and written + * | | |Writing to CRPT_HMAC_DMACNT while the SHA/HMAC accelerator is operating doesn't affect the current SHA/HMAC operation + * | | |But the value of CRPT_HMAC_DMACNT will be updated later on + * | | |Consequently, software can prepare the byte count of data for the next SHA/HMAC operation. + * | | |In Non-DMA mode, CRPT_HMAC_DMACNT must be set as the byte count of the last block before feeding in the last block of data. + * @var CRPT_T::HMAC_DATIN + * Offset: 0x354 SHA/HMAC Engine Non-DMA Mode Data Input Port Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DATIN |SHA/HMAC Engine Input Port + * | | |CPU feeds data to SHA/HMAC engine through this port by checking CRPT_HMAC_STS + * | | |Feed data as DATINREQ is 1. + * @var CRPT_T::ECC_CTL + * Offset: 0x800 ECC Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |START |ECC Accelerator Start + * | | |0 = No effect. + * | | |1 = Start ECC accelerator. BUSY flag will be set. + * | | |This bit is always 0 when it's read back. + * | | |ECC accelerator will ignore this START signal when BUSY flag is 1. + * |[1] |STOP |ECC Accelerator Stop + * | | |0 = No effect. + * | | |1 = Abort ECC accelerator and make it into idle state. + * | | |This bit is always 0 when it's read back. + * | | |Remember to clear ECC interrupt flag after stopping ECC accelerator. + * |[7] |DMAEN |ECC Accelerator DMA Enable Control + * | | |0 = ECC DMA engine Disabled. + * | | |1 = ECC DMA engine Enabled. + * | | |Only when START and DMAEN are 1, ECC DMA engine will be active + * |[8] |FSEL |Field Selection + * | | |0 = Binary Field (GF(2^m)). + * | | |1 = Prime Field (GF(p)). + * |[10:9] |ECCOP |Point Operation for BF and PF + * | | |00 = Point multiplication :. + * | | |(POINTX1, POINTY1) = SCALARK * (POINTX1, POINTY1). + * | | |01 = Modulus operation : choose by MODOP (CRPT_ECC_CTL[12:11]). + * | | |10 = Point addition :. + * | | |(POINTX1, POINTY1) = (POINTX1, POINTY1) +. + * | | |(POINTX2, POINTY2) + * | | |11 = Point doubling :. + * | | |(POINTX1, POINTY1) = 2 * (POINTX1, POINTY1). + * | | |Besides above three input data, point operations still need the parameters of elliptic curve (CURVEA, CURVEB, CURVEN and CURVEM) as shown in Figure 6.27-11 + * |[12:11] |MODOP |Modulus Operation for PF + * | | |00 = Division :. + * | | |POINTX1 = (POINTY1 / POINTX1) % CURVEN. + * | | |01 = Multiplication :. + * | | |POINTX1 = (POINTX1 * POINTY1) % CURVEN. + * | | |10 = Addition :. + * | | |POINTX1 = (POINTX1 + POINTY1) % CURVEN. + * | | |11 = Subtraction :. + * | | |POINTX1 = (POINTX1 - POINTY1) % CURVEN. + * | | |MODOP is active only when ECCOP = 01. + * |[16] |LDP1 |The Control Signal of Register for the X and Y Coordinate of the First Point (POINTX1, POINTY1) + * | | |0 = The register for POINTX1 and POINTY1 is not modified by DMA or user. + * | | |1 = The register for POINTX1 and POINTY1 is modified by DMA or user. + * |[17] |LDP2 |The Control Signal of Register for the X and Y Coordinate of the Second Point (POINTX2, POINTY2) + * | | |0 = The register for POINTX2 and POINTY2 is not modified by DMA or user. + * | | |1 = The register for POINTX2 and POINTY2 is modified by DMA or user. + * |[18] |LDA |The Control Signal of Register for the Parameter CURVEA of Elliptic Curve + * | | |0 = The register for CURVEA is not modified by DMA or user. + * | | |1 = The register for CURVEA is modified by DMA or user. + * |[19] |LDB |The Control Signal of Register for the Parameter CURVEB of Elliptic Curve + * | | |0 = The register for CURVEB is not modified by DMA or user. + * | | |1 = The register for CURVEB is modified by DMA or user. + * |[20] |LDN |The Control Signal of Register for the Parameter CURVEN of Elliptic Curve + * | | |0 = The register for CURVEN is not modified by DMA or user. + * | | |1 = The register for CURVEN is modified by DMA or user. + * |[21] |LDK |The Control Signal of Register for SCALARK + * | | |0 = The register for SCALARK is not modified by DMA or user. + * | | |1 = The register for SCALARK is modified by DMA or user. + * |[31:22] |CURVEM |The key length of elliptic curve. + * @var CRPT_T::ECC_STS + * Offset: 0x804 ECC Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSY |ECC Accelerator Busy Flag + * | | |0 = The ECC accelerator is idle or finished. + * | | |1 = The ECC accelerator is under processing and protects all registers. + * | | |Remember to clear ECC interrupt flag after ECC accelerator finished + * |[1] |DMABUSY |ECC DMA Busy Flag + * | | |0 = ECC DMA is idle or finished. + * | | |1 = ECC DMA is busy. + * |[16] |BUSERR |ECC DMA Access Bus Error Flag + * | | |0 = No error. + * | | |1 = Bus error will stop DMA operation and ECC accelerator. + * @var CRPT_T::ECC_X1[18] + * Offset: 0x808 ~ 0x84C ECC The X-coordinate word 0 ~ 17 of the first point + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |POINTX1 |ECC the x-coordinate Value of the First Point (POINTX1) + * | | |For B-163 or K-163, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_05 + * | | |For B-233 or K-233, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_07 + * | | |For B-283 or K-283, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_08 + * | | |For B-409 or K-409, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_12 + * | | |For B-571 or K-571, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_17 + * | | |For P-192, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_05 + * | | |For P-224, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_06 + * | | |For P-256, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_07 + * | | |For P-384, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_11 + * | | |For P-521, POINTX1 is stored in CRPT_ECC_X1_00~CRPT_ECC_X1_16 + * @var CRPT_T::ECC_Y1[18] + * Offset: 0x850 ~ 0x894 ECC The Y-coordinate word 0 ~ 17 of the first point + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |POINTY1 |ECC the Y-coordinate Value of the First Point (POINTY1) + * | | |For B-163 or K-163, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_05 + * | | |For B-233 or K-233, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_07 + * | | |For B-283 or K-283, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_08 + * | | |For B-409 or K-409, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_12 + * | | |For B-571 or K-571, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_17 + * | | |For P-192, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_05 + * | | |For P-224, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_06 + * | | |For P-256, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_07 + * | | |For P-384, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_11 + * | | |For P-521, POINTY1 is stored in CRPT_ECC_Y1_00~CRPT_ECC_Y1_16 + * @var CRPT_T::ECC_X2[18] + * Offset: 0x898 ~ 0x8DC ECC The X-coordinate word 0 ~ 17 of the second point + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |POINTX2 |ECC the x-coordinate Value of the Second Point (POINTX2) + * | | |For B-163 or K-163, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_05 + * | | |For B-233 or K-233, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_07 + * | | |For B-283 or K-283, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_08 + * | | |For B-409 or K-409, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_12 + * | | |For B-571 or K-571, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_17 + * | | |For P-192, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_05 + * | | |For P-224, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_06 + * | | |For P-256, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_07 + * | | |For P-384, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_11 + * | | |For P-521, POINTX2 is stored in CRPT_ECC_X2_00~CRPT_ECC_X2_16 + * @var CRPT_T::ECC_Y2[18] + * Offset: 0x8E0 ~ 0x924 ECC The Y-coordinate word 0 ~ 17 of the second point + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |POINTY2 |ECC the Y-coordinate Value of the Second Point (POINTY2) + * | | |For B-163 or K-163, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_05 + * | | |For B-233 or K-233, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_07 + * | | |For B-283 or K-283, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_08 + * | | |For B-409 or K-409, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_12 + * | | |For B-571 or K-571, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_17 + * | | |For P-192, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_05 + * | | |For P-224, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_06 + * | | |For P-256, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_07 + * | | |For P-384, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_11 + * | | |For P-521, POINTY2 is stored in CRPT_ECC_Y2_00~CRPT_ECC_Y2_16 + * @var CRPT_T::ECC_A[18] + * Offset: 0x928 ~ 0x96C ECC The parameter CURVEA word 0 ~ 17 of elliptic curve + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CURVEA |ECC the Parameter CURVEA Value of Elliptic Curve (CURVEA) + * | | |The formula of elliptic curve is y2=x3+CURVEA*x+CURVEB in GF(p) and y2+x*y=x3+CURVEA*x2+CURVEB in GF(2^m). + * | | |For B-163 or K-163, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_05 + * | | |For B-233 or K-233, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_07 + * | | |For B-283 or K-283, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_08 + * | | |For B-409 or K-409, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_12 + * | | |For B-571 or K-571, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_17 + * | | |For P-192, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_05 + * | | |For P-224, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_06 + * | | |For P-256, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_07 + * | | |For P-384, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_11 + * | | |For P-521, CURVEA is stored in CRPT_ECC_A_00~CRPT_ECC_A_16 + * @var CRPT_T::ECC_B[18] + * Offset: 0x970 ~ 0x9B4 ECC The parameter CURVEB word 0 ~ 17 of elliptic curve + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CURVEB |ECC the Parameter CURVEB Value of Elliptic Curve (CURVEA) + * | | |The formula of elliptic curve is y2=x3+CURVEA*x+CURVEB in GF(p) and y2+x*y=x3+CURVEA*x2+CURVEB in GF(2^m). + * | | |For B-163 or K-163, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_05 + * | | |For B-233 or K-233, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_07 + * | | |For B-283 or K-283, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_08 + * | | |For B-409 or K-409, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_12 + * | | |For B-521 or K-521, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_17 + * | | |For P-192, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_05 + * | | |For P-224, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_06 + * | | |For P-256, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_07 + * | | |For P-384, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_11 + * | | |For P-521, CURVEB is stored in CRPT_ECC_B_00~CRPT_ECC_B_16 + * @var CRPT_T::ECC_N[18] + * Offset: 0x9B8 ~ 0x9FC ECC The parameter CURVEN word 0 ~ 17 of elliptic curve + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CURVEN |ECC the Parameter CURVEN Value of Elliptic Curve (CURVEN) + * | | |In GF(p), CURVEN is the prime p. + * | | |In GF(2^m), CURVEN is the irreducible polynomial. + * | | |For B-163 or K-163, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_05 + * | | |For B-233 or K-233, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_07 + * | | |For B-283 or K-283, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_08 + * | | |For B-409 or K-409, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_12 + * | | |For B-571 or K-571, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_17 + * | | |For P-192, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_05 + * | | |For P-224, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_06 + * | | |For P-256, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_07 + * | | |For P-384, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_11 + * | | |For P-521, CURVEN is stored in CRPT_ECC_N_00~CRPT_ECC_N_16 + * @var CRPT_T::ECC_K[18] + * Offset: 0xA00 ~ 0xA44 ECC The scalar SCALARK word0 of point multiplication + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SCALARK |ECC the Scalar SCALARK Value of Point Multiplication(SCALARK) + * | | |Because the SCALARK usually stores the private key, ECC accelerator do not allow to read the register SCALARK. + * | | |For B-163 or K-163, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_05 + * | | |For B-233 or K-233, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_07 + * | | |For B-283 or K-283, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_08 + * | | |For B-409 or K-409, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_12 + * | | |For B-571 or K-571, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_17 + * | | |For P-192, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_05 + * | | |For P-224, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_06 + * | | |For P-256, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_07 + * | | |For P-384, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_11 + * | | |For P-521, SCALARK is stored in CRPT_ECC_K_00~CRPT_ECC_K_16 + * @var CRPT_T::ECC_SADDR + * Offset: 0xA48 ECC DMA Source Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SADDR |ECC DMA Source Address + * | | |The ECC accelerator supports DMA function to transfer the DATA and PARAMETER between + * | | |SRAM memory space and ECC accelerator. The SADDR keeps the source address of the data + * | | |buffer where the source text is stored. Based on the source address, the ECC accelerator + * | | |can read the DATA and PARAMETER from SRAM memory space and do ECC operation. The start + * | | |of source address should be located at word boundary. That is, bit 1 and 0 of SADDR are + * | | |ignored. SADDR can be read and written. In DMA mode, software must update the CRPT_ECC_SADDR + * | | |before triggering START. + * @var CRPT_T::ECC_DADDR + * Offset: 0xA4C ECC DMA Destination Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DADDR |ECC DMA Destination Address + * | | |The ECC accelerator supports DMA function to transfer the DATA and PARAMETER between system memory and ECC accelerator + * | | |The DADDR keeps the destination address of the data buffer where output data of ECC engine will be stored + * | | |Based on the destination address, the ECC accelerator can write the result data back to system memory after the ECC operation is finished + * | | |The start of destination address should be located at word boundary + * | | |That is, bit 1 and 0 of DADDR are ignored + * | | |DADDR can be read and written + * | | |In DMA mode, software must update the CRPT_ECC_DADDR before triggering START + * @var CRPT_T::ECC_STARTREG + * Offset: 0xA50 ECC Starting Address of Updated Registers + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |STARTREG |ECC Starting Address of Updated Registers + * | | |The address of the updated registers that DMA feeds the first data or parameter to ECC engine + * | | |When ECC engine is active, ECC accelerator does not allow users to modify STARTREG + * | | |For example, we want to updated input data from register CRPT_ECC POINTX1 + * | | |Thus, the value of STARTREG is 0x808. + * @var CRPT_T::ECC_WORDCNT + * Offset: 0xA54 ECC DMA Word Count + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |WORDCNT |ECC DMA Word Count + * | | |The CRPT_ECC_WORDCNT keeps the word count of source data that is for the required input data of ECC accelerator with various operations in DMA mode + * | | |Although CRPT_ECC_WORDCNT is 32-bit, the maximum of word count in ECC accelerator is 144 words + * | | |CRPT_ECC_WORDCNT can be read and written + */ + __IO uint32_t INTEN; /*!< [0x0000] Crypto Interrupt Enable Control Register */ + __IO uint32_t INTSTS; /*!< [0x0004] Crypto Interrupt Flag */ + __IO uint32_t PRNG_CTL; /*!< [0x0008] PRNG Control Register */ + __O uint32_t PRNG_SEED; /*!< [0x000c] Seed for PRNG */ + __I uint32_t PRNG_KEY[8]; /*!< [0x0010] ~ [0x002c] PRNG Generated Key0 ~ Key7 */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE0[8]; + /// @endcond //HIDDEN_SYMBOLS + __I uint32_t AES_FDBCK[4]; /*!< [0x0050] ~ [0x005c] AES Engine Output Feedback Data after Cryptographic Operation */ + __I uint32_t TDES_FDBCKH; /*!< [0x0060] TDES/DES Engine Output Feedback High Word Data after Cryptographic Operation */ + __I uint32_t TDES_FDBCKL; /*!< [0x0064] TDES/DES Engine Output Feedback Low Word Data after Cryptographic Operation */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE1[38]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t AES_CTL; /*!< [0x0100] AES Control Register */ + __I uint32_t AES_STS; /*!< [0x0104] AES Engine Flag */ + __IO uint32_t AES_DATIN; /*!< [0x0108] AES Engine Data Input Port Register */ + __I uint32_t AES_DATOUT; /*!< [0x010c] AES Engine Data Output Port Register */ + __IO uint32_t AES0_KEY[8]; /*!< [0x0110] ~ [0x012c] AES Key Word 0~7 Register for Channel 0 */ + __IO uint32_t AES0_IV[4]; /*!< [0x0130] ~ [0x013c] AES Initial Vector Word 0 ~ 3 Register for Channel 0 */ + __IO uint32_t AES0_SADDR; /*!< [0x0140] AES DMA Source Address Register for Channel 0 */ + __IO uint32_t AES0_DADDR; /*!< [0x0144] AES DMA Destination Address Register for Channel 0 */ + __IO uint32_t AES0_CNT; /*!< [0x0148] AES Byte Count Register for Channel 0 */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE2[109]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t HMAC_CTL; /*!< [0x0300] SHA/HMAC Control Register */ + __I uint32_t HMAC_STS; /*!< [0x0304] SHA/HMAC Status Flag */ + __I uint32_t HMAC_DGST[16]; /*!< [0x0308] ~ [0x0344] SHA/HMAC Digest Message 0~15 */ + __IO uint32_t HMAC_KEYCNT; /*!< [0x0348] SHA/HMAC Key Byte Count Register */ + __IO uint32_t HMAC_SADDR; /*!< [0x034c] SHA/HMAC DMA Source Address Register */ + __IO uint32_t HMAC_DMACNT; /*!< [0x0350] SHA/HMAC Byte Count Register */ + __IO uint32_t HMAC_DATIN; /*!< [0x0354] SHA/HMAC Engine Non-DMA Mode Data Input Port Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE3[298]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t ECC_CTL; /*!< [0x0800] ECC Control Register */ + __I uint32_t ECC_STS; /*!< [0x0804] ECC Status Register */ + __IO uint32_t ECC_X1[18]; /*!< [0x0808] ~ [0x084c] ECC The X-coordinate word 0~17 of the first point */ + __IO uint32_t ECC_Y1[18]; /*!< [0x0850] ~ [0x0894] ECC The Y-coordinate word 0~17 of the first point */ + __IO uint32_t ECC_X2[18]; /*!< [0x0898] ~ [0x08dc] ECC The X-coordinate word 0~17 of the second point */ + __IO uint32_t ECC_Y2[18]; /*!< [0x08e0] ~ [0x0924] ECC The Y-coordinate word 0~17 of the second point */ + __IO uint32_t ECC_A[18]; /*!< [0x0928] ~ [0x096c] ECC The parameter CURVEA word 0~17 of elliptic curve */ + __IO uint32_t ECC_B[18]; /*!< [0x0970] ~ [0x09b4] ECC The parameter CURVEB word 0~17 of elliptic curve */ + __IO uint32_t ECC_N[18]; /*!< [0x09b8] ~ [0x09fc] ECC The parameter CURVEN word 0~17 of elliptic curve */ + __O uint32_t ECC_K[18]; /*!< [0x0a00] ~ [0x0a44] ECC The scalar SCALARK word 0~17 of point multiplication */ + __IO uint32_t ECC_SADDR; /*!< [0x0a48] ECC DMA Source Address Register */ + __IO uint32_t ECC_DADDR; /*!< [0x0a4c] ECC DMA Destination Address Register */ + __IO uint32_t ECC_STARTREG; /*!< [0x0a50] ECC Starting Address of Updated Registers */ + __IO uint32_t ECC_WORDCNT; /*!< [0x0a54] ECC DMA Word Count */ + /// @cond HIDDEN_SYMBOLS + uint32_t RESERVE4[358]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t ECC_FSM_DBG; /* Offset 0xFF0: ECC FSM Debug Register */ + /// @cond HIDDEN_SYMBOLS + uint32_t RESERVE5[3]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t RSA_CTL; /* Offset 0x1000: RSA Control Register */ + __IO uint32_t RSA_STS; /* Offset 0x1004: RSA Status Register */ + __IO uint32_t RSA_M[128]; /* Offset 0x1008: RSA the base of exponentiation words */ + __IO uint32_t RSA_E[128]; /* Offset 0x1208: RSA the exponent of exponentiation words */ + __IO uint32_t RSA_N[128]; /* Offset 0x1408: RSA the base of modulus operation word */ + __IO uint32_t RSA_C[128]; /* Offset 0x1608: RSA the constant value of Montgomery domain words */ + __IO uint32_t RSA_SADDR; /* Offset 0x1808: RSA DMA Source Address Register */ + __IO uint32_t RSA_DADDR; /* Offset 0x180C: RSA DMA Destination Address Register */ + __IO uint32_t RSA_STARTREG; /* Offset 0x1810: RSA Starting Address of Updated Registers */ + __IO uint32_t RSA_WORDCNT; /* Offset 0x1814: RSA DMA Word Count */ +} CRPT_T; + +#define CRPT ((CRPT_T *)0xB001C000) + +/** + @addtogroup CRPT_CONST CRPT Bit Field Definition + Constant Definitions for CRPT Controller +@{ */ + +#define CRPT_INTEN_AESIEN_Pos (0) /*!< CRPT_T::INTEN: AESIEN Position */ +#define CRPT_INTEN_AESIEN_Msk (0x1ul << CRPT_INTEN_AESIEN_Pos) /*!< CRPT_T::INTEN: AESIEN Mask */ + +#define CRPT_INTEN_AESEIEN_Pos (1) /*!< CRPT_T::INTEN: AESEIEN Position */ +#define CRPT_INTEN_AESEIEN_Msk (0x1ul << CRPT_INTEN_AESEIEN_Pos) /*!< CRPT_T::INTEN: AESEIEN Mask */ + +#define CRPT_INTEN_TDESIEN_Pos (8) /*!< CRPT_T::INTEN: TDESIEN Position */ +#define CRPT_INTEN_TDESIEN_Msk (0x1ul << CRPT_INTEN_TDESIEN_Pos) /*!< CRPT_T::INTEN: TDESIEN Mask */ + +#define CRPT_INTEN_TDESEIEN_Pos (9) /*!< CRPT_T::INTEN: TDESEIEN Position */ +#define CRPT_INTEN_TDESEIEN_Msk (0x1ul << CRPT_INTEN_TDESEIEN_Pos) /*!< CRPT_T::INTEN: TDESEIEN Mask */ + +#define CRPT_INTEN_PRNGIEN_Pos (16) /*!< CRPT_T::INTEN: PRNGIEN Position */ +#define CRPT_INTEN_PRNGIEN_Msk (0x1ul << CRPT_INTEN_PRNGIEN_Pos) /*!< CRPT_T::INTEN: PRNGIEN Mask */ + +#define CRPT_INTEN_ECCIEN_Pos (22) /*!< CRPT_T::INTEN: ECCIEN Position */ +#define CRPT_INTEN_ECCIEN_Msk (0x1ul << CRPT_INTEN_ECCIEN_Pos) /*!< CRPT_T::INTEN: ECCIEN Mask */ + +#define CRPT_INTEN_ECCEIEN_Pos (23) /*!< CRPT_T::INTEN: ECCEIEN Position */ +#define CRPT_INTEN_ECCEIEN_Msk (0x1ul << CRPT_INTEN_ECCEIEN_Pos) /*!< CRPT_T::INTEN: ECCEIEN Mask */ + +#define CRPT_INTEN_HMACIEN_Pos (24) /*!< CRPT_T::INTEN: HMACIEN Position */ +#define CRPT_INTEN_HMACIEN_Msk (0x1ul << CRPT_INTEN_HMACIEN_Pos) /*!< CRPT_T::INTEN: HMACIEN Mask */ + +#define CRPT_INTEN_HMACEIEN_Pos (25) /*!< CRPT_T::INTEN: HMACEIEN Position */ +#define CRPT_INTEN_HMACEIEN_Msk (0x1ul << CRPT_INTEN_HMACEIEN_Pos) /*!< CRPT_T::INTEN: HMACEIEN Mask */ + +#define CRPT_INTSTS_AESIF_Pos (0) /*!< CRPT_T::INTSTS: AESIF Position */ +#define CRPT_INTSTS_AESIF_Msk (0x1ul << CRPT_INTSTS_AESIF_Pos) /*!< CRPT_T::INTSTS: AESIF Mask */ + +#define CRPT_INTSTS_AESEIF_Pos (1) /*!< CRPT_T::INTSTS: AESEIF Position */ +#define CRPT_INTSTS_AESEIF_Msk (0x1ul << CRPT_INTSTS_AESEIF_Pos) /*!< CRPT_T::INTSTS: AESEIF Mask */ + +#define CRPT_INTSTS_TDESIF_Pos (8) /*!< CRPT_T::INTSTS: TDESIF Position */ +#define CRPT_INTSTS_TDESIF_Msk (0x1ul << CRPT_INTSTS_TDESIF_Pos) /*!< CRPT_T::INTSTS: TDESIF Mask */ + +#define CRPT_INTSTS_TDESEIF_Pos (9) /*!< CRPT_T::INTSTS: TDESEIF Position */ +#define CRPT_INTSTS_TDESEIF_Msk (0x1ul << CRPT_INTSTS_TDESEIF_Pos) /*!< CRPT_T::INTSTS: TDESEIF Mask */ + +#define CRPT_INTSTS_PRNGIF_Pos (16) /*!< CRPT_T::INTSTS: PRNGIF Position */ +#define CRPT_INTSTS_PRNGIF_Msk (0x1ul << CRPT_INTSTS_PRNGIF_Pos) /*!< CRPT_T::INTSTS: PRNGIF Mask */ + +#define CRPT_INTSTS_ECCIF_Pos (22) /*!< CRPT_T::INTSTS: ECCIF Position */ +#define CRPT_INTSTS_ECCIF_Msk (0x1ul << CRPT_INTSTS_ECCIF_Pos) /*!< CRPT_T::INTSTS: ECCIF Mask */ + +#define CRPT_INTSTS_ECCEIF_Pos (23) /*!< CRPT_T::INTSTS: ECCEIF Position */ +#define CRPT_INTSTS_ECCEIF_Msk (0x1ul << CRPT_INTSTS_ECCEIF_Pos) /*!< CRPT_T::INTSTS: ECCEIF Mask */ + +#define CRPT_INTSTS_HMACIF_Pos (24) /*!< CRPT_T::INTSTS: HMACIF Position */ +#define CRPT_INTSTS_HMACIF_Msk (0x1ul << CRPT_INTSTS_HMACIF_Pos) /*!< CRPT_T::INTSTS: HMACIF Mask */ + +#define CRPT_INTSTS_HMACEIF_Pos (25) /*!< CRPT_T::INTSTS: HMACEIF Position */ +#define CRPT_INTSTS_HMACEIF_Msk (0x1ul << CRPT_INTSTS_HMACEIF_Pos) /*!< CRPT_T::INTSTS: HMACEIF Mask */ + +#define CRPT_PRNG_CTL_START_Pos (0) /*!< CRPT_T::PRNG_CTL: START Position */ +#define CRPT_PRNG_CTL_START_Msk (0x1ul << CRPT_PRNG_CTL_START_Pos) /*!< CRPT_T::PRNG_CTL: START Mask */ + +#define CRPT_PRNG_CTL_SEEDRLD_Pos (1) /*!< CRPT_T::PRNG_CTL: SEEDRLD Position */ +#define CRPT_PRNG_CTL_SEEDRLD_Msk (0x1ul << CRPT_PRNG_CTL_SEEDRLD_Pos) /*!< CRPT_T::PRNG_CTL: SEEDRLD Mask */ + +#define CRPT_PRNG_CTL_KEYSZ_Pos (2) /*!< CRPT_T::PRNG_CTL: KEYSZ Position */ +#define CRPT_PRNG_CTL_KEYSZ_Msk (0x3ul << CRPT_PRNG_CTL_KEYSZ_Pos) /*!< CRPT_T::PRNG_CTL: KEYSZ Mask */ + +#define CRPT_PRNG_CTL_BUSY_Pos (8) /*!< CRPT_T::PRNG_CTL: BUSY Position */ +#define CRPT_PRNG_CTL_BUSY_Msk (0x1ul << CRPT_PRNG_CTL_BUSY_Pos) /*!< CRPT_T::PRNG_CTL: BUSY Mask */ + +#define CRPT_PRNG_SEED_SEED_Pos (0) /*!< CRPT_T::PRNG_SEED: SEED Position */ +#define CRPT_PRNG_SEED_SEED_Msk (0xfffffffful << CRPT_PRNG_SEED_SEED_Pos) /*!< CRPT_T::PRNG_SEED: SEED Mask */ + +#define CRPT_PRNG_KEYx_KEY_Pos (0) /*!< CRPT_T::PRNG_KEY[8]: KEY Position */ +#define CRPT_PRNG_KEYx_KEY_Msk (0xfffffffful << CRPT_PRNG_KEYx_KEY_Pos) /*!< CRPT_T::PRNG_KEY[8]: KEY Mask */ + +#define CRPT_AES_FDBCKx_FDBCK_Pos (0) /*!< CRPT_T::AES_FDBCK[4]: FDBCK Position */ +#define CRPT_AES_FDBCKx_FDBCK_Msk (0xfffffffful << CRPT_AES_FDBCKx_FDBCK_Pos) /*!< CRPT_T::AES_FDBCK[4]: FDBCK Mask */ + +#define CRPT_TDES_FDBCKH_FDBCK_Pos (0) /*!< CRPT_T::TDES_FDBCKH: FDBCK Position */ +#define CRPT_TDES_FDBCKH_FDBCK_Msk (0xfffffffful << CRPT_TDES_FDBCKH_FDBCK_Pos) /*!< CRPT_T::TDES_FDBCKH: FDBCK Mask */ + +#define CRPT_TDES_FDBCKL_FDBCK_Pos (0) /*!< CRPT_T::TDES_FDBCKL: FDBCK Position */ +#define CRPT_TDES_FDBCKL_FDBCK_Msk (0xfffffffful << CRPT_TDES_FDBCKL_FDBCK_Pos) /*!< CRPT_T::TDES_FDBCKL: FDBCK Mask */ + +#define CRPT_AES_CTL_START_Pos (0) /*!< CRPT_T::AES_CTL: START Position */ +#define CRPT_AES_CTL_START_Msk (0x1ul << CRPT_AES_CTL_START_Pos) /*!< CRPT_T::AES_CTL: START Mask */ + +#define CRPT_AES_CTL_STOP_Pos (1) /*!< CRPT_T::AES_CTL: STOP Position */ +#define CRPT_AES_CTL_STOP_Msk (0x1ul << CRPT_AES_CTL_STOP_Pos) /*!< CRPT_T::AES_CTL: STOP Mask */ + +#define CRPT_AES_CTL_KEYSZ_Pos (2) /*!< CRPT_T::AES_CTL: KEYSZ Position */ +#define CRPT_AES_CTL_KEYSZ_Msk (0x3ul << CRPT_AES_CTL_KEYSZ_Pos) /*!< CRPT_T::AES_CTL: KEYSZ Mask */ + +#define CRPT_AES_CTL_DMALAST_Pos (5) /*!< CRPT_T::AES_CTL: DMALAST Position */ +#define CRPT_AES_CTL_DMALAST_Msk (0x1ul << CRPT_AES_CTL_DMALAST_Pos) /*!< CRPT_T::AES_CTL: DMALAST Mask */ + +#define CRPT_AES_CTL_DMACSCAD_Pos (6) /*!< CRPT_T::AES_CTL: DMACSCAD Position */ +#define CRPT_AES_CTL_DMACSCAD_Msk (0x1ul << CRPT_AES_CTL_DMACSCAD_Pos) /*!< CRPT_T::AES_CTL: DMACSCAD Mask */ + +#define CRPT_AES_CTL_DMAEN_Pos (7) /*!< CRPT_T::AES_CTL: DMAEN Position */ +#define CRPT_AES_CTL_DMAEN_Msk (0x1ul << CRPT_AES_CTL_DMAEN_Pos) /*!< CRPT_T::AES_CTL: DMAEN Mask */ + +#define CRPT_AES_CTL_OPMODE_Pos (8) /*!< CRPT_T::AES_CTL: OPMODE Position */ +#define CRPT_AES_CTL_OPMODE_Msk (0xfful << CRPT_AES_CTL_OPMODE_Pos) /*!< CRPT_T::AES_CTL: OPMODE Mask */ + +#define CRPT_AES_CTL_ENCRPT_Pos (16) /*!< CRPT_T::AES_CTL: ENCRPT Position */ +#define CRPT_AES_CTL_ENCRPT_Msk (0x1ul << CRPT_AES_CTL_ENCRPT_Pos) /*!< CRPT_T::AES_CTL: ENCRPT Mask */ + +#define CRPT_AES_CTL_OUTSWAP_Pos (22) /*!< CRPT_T::AES_CTL: OUTSWAP Position */ +#define CRPT_AES_CTL_OUTSWAP_Msk (0x1ul << CRPT_AES_CTL_OUTSWAP_Pos) /*!< CRPT_T::AES_CTL: OUTSWAP Mask */ + +#define CRPT_AES_CTL_INSWAP_Pos (23) /*!< CRPT_T::AES_CTL: INSWAP Position */ +#define CRPT_AES_CTL_INSWAP_Msk (0x1ul << CRPT_AES_CTL_INSWAP_Pos) /*!< CRPT_T::AES_CTL: INSWAP Mask */ + +#define CRPT_AES_CTL_CHANNEL_Pos (24) /*!< CRPT_T::AES_CTL: CHANNEL Position */ +#define CRPT_AES_CTL_CHANNEL_Msk (0x3ul << CRPT_AES_CTL_CHANNEL_Pos) /*!< CRPT_T::AES_CTL: CHANNEL Mask */ + +#define CRPT_AES_CTL_KEYUNPRT_Pos (26) /*!< CRPT_T::AES_CTL: KEYUNPRT Position */ +#define CRPT_AES_CTL_KEYUNPRT_Msk (0x1ful << CRPT_AES_CTL_KEYUNPRT_Pos) /*!< CRPT_T::AES_CTL: KEYUNPRT Mask */ + +#define CRPT_AES_CTL_KEYPRT_Pos (31) /*!< CRPT_T::AES_CTL: KEYPRT Position */ +#define CRPT_AES_CTL_KEYPRT_Msk (0x1ul << CRPT_AES_CTL_KEYPRT_Pos) /*!< CRPT_T::AES_CTL: KEYPRT Mask */ + +#define CRPT_AES_STS_BUSY_Pos (0) /*!< CRPT_T::AES_STS: BUSY Position */ +#define CRPT_AES_STS_BUSY_Msk (0x1ul << CRPT_AES_STS_BUSY_Pos) /*!< CRPT_T::AES_STS: BUSY Mask */ + +#define CRPT_AES_STS_INBUFEMPTY_Pos (8) /*!< CRPT_T::AES_STS: INBUFEMPTY Position */ +#define CRPT_AES_STS_INBUFEMPTY_Msk (0x1ul << CRPT_AES_STS_INBUFEMPTY_Pos) /*!< CRPT_T::AES_STS: INBUFEMPTY Mask */ + +#define CRPT_AES_STS_INBUFFULL_Pos (9) /*!< CRPT_T::AES_STS: INBUFFULL Position */ +#define CRPT_AES_STS_INBUFFULL_Msk (0x1ul << CRPT_AES_STS_INBUFFULL_Pos) /*!< CRPT_T::AES_STS: INBUFFULL Mask */ + +#define CRPT_AES_STS_INBUFERR_Pos (10) /*!< CRPT_T::AES_STS: INBUFERR Position */ +#define CRPT_AES_STS_INBUFERR_Msk (0x1ul << CRPT_AES_STS_INBUFERR_Pos) /*!< CRPT_T::AES_STS: INBUFERR Mask */ + +#define CRPT_AES_STS_CNTERR_Pos (12) /*!< CRPT_T::AES_STS: CNTERR Position */ +#define CRPT_AES_STS_CNTERR_Msk (0x1ul << CRPT_AES_STS_CNTERR_Pos) /*!< CRPT_T::AES_STS: CNTERR Mask */ + +#define CRPT_AES_STS_OUTBUFEMPTY_Pos (16) /*!< CRPT_T::AES_STS: OUTBUFEMPTY Position */ +#define CRPT_AES_STS_OUTBUFEMPTY_Msk (0x1ul << CRPT_AES_STS_OUTBUFEMPTY_Pos) /*!< CRPT_T::AES_STS: OUTBUFEMPTY Mask */ + +#define CRPT_AES_STS_OUTBUFFULL_Pos (17) /*!< CRPT_T::AES_STS: OUTBUFFULL Position */ +#define CRPT_AES_STS_OUTBUFFULL_Msk (0x1ul << CRPT_AES_STS_OUTBUFFULL_Pos) /*!< CRPT_T::AES_STS: OUTBUFFULL Mask */ + +#define CRPT_AES_STS_OUTBUFERR_Pos (18) /*!< CRPT_T::AES_STS: OUTBUFERR Position */ +#define CRPT_AES_STS_OUTBUFERR_Msk (0x1ul << CRPT_AES_STS_OUTBUFERR_Pos) /*!< CRPT_T::AES_STS: OUTBUFERR Mask */ + +#define CRPT_AES_STS_BUSERR_Pos (20) /*!< CRPT_T::AES_STS: BUSERR Position */ +#define CRPT_AES_STS_BUSERR_Msk (0x1ul << CRPT_AES_STS_BUSERR_Pos) /*!< CRPT_T::AES_STS: BUSERR Mask */ + +#define CRPT_AES_DATIN_DATIN_Pos (0) /*!< CRPT_T::AES_DATIN: DATIN Position */ +#define CRPT_AES_DATIN_DATIN_Msk (0xfffffffful << CRPT_AES_DATIN_DATIN_Pos) /*!< CRPT_T::AES_DATIN: DATIN Mask */ + +#define CRPT_AES_DATOUT_DATOUT_Pos (0) /*!< CRPT_T::AES_DATOUT: DATOUT Position */ +#define CRPT_AES_DATOUT_DATOUT_Msk (0xfffffffful << CRPT_AES_DATOUT_DATOUT_Pos) /*!< CRPT_T::AES_DATOUT: DATOUT Mask */ + +#define CRPT_AES0_KEYx_KEY_Pos (0) /*!< CRPT_T::AES0_KEY[8]: KEY Position */ +#define CRPT_AES0_KEYx_KEY_Msk (0xfffffffful << CRPT_AES0_KEYx_KEY_Pos) /*!< CRPT_T::AES0_KEY[8]: KEY Mask */ + +#define CRPT_AES0_IVx_IV_Pos (0) /*!< CRPT_T::AES0_IV[4]: IV Position */ +#define CRPT_AES0_IVx_IV_Msk (0xfffffffful << CRPT_AES0_IVx_IV_Pos) /*!< CRPT_T::AES0_IV[4]: IV Mask */ + +#define CRPT_AES0_SADDR_SADDR_Pos (0) /*!< CRPT_T::AES0_SADDR: SADDR Position */ +#define CRPT_AES0_SADDR_SADDR_Msk (0xfffffffful << CRPT_AES0_SADDR_SADDR_Pos) /*!< CRPT_T::AES0_SADDR: SADDR Mask */ + +#define CRPT_AES0_DADDR_DADDR_Pos (0) /*!< CRPT_T::AES0_DADDR: DADDR Position */ +#define CRPT_AES0_DADDR_DADDR_Msk (0xfffffffful << CRPT_AES0_DADDR_DADDR_Pos) /*!< CRPT_T::AES0_DADDR: DADDR Mask */ + +#define CRPT_AES0_CNT_CNT_Pos (0) /*!< CRPT_T::AES0_CNT: CNT Position */ +#define CRPT_AES0_CNT_CNT_Msk (0xfffffffful << CRPT_AES0_CNT_CNT_Pos) /*!< CRPT_T::AES0_CNT: CNT Mask */ + +#define CRPT_HMAC_CTL_START_Pos (0) /*!< CRPT_T::HMAC_CTL: START Position */ +#define CRPT_HMAC_CTL_START_Msk (0x1ul << CRPT_HMAC_CTL_START_Pos) /*!< CRPT_T::HMAC_CTL: START Mask */ + +#define CRPT_HMAC_CTL_STOP_Pos (1) /*!< CRPT_T::HMAC_CTL: STOP Position */ +#define CRPT_HMAC_CTL_STOP_Msk (0x1ul << CRPT_HMAC_CTL_STOP_Pos) /*!< CRPT_T::HMAC_CTL: STOP Mask */ + +#define CRPT_HMAC_CTL_HMACEN_Pos (4) /*!< CRPT_T::HMAC_CTL: HMACEN Position */ +#define CRPT_HMAC_CTL_HMACEN_Msk (0x1ul << CRPT_HMAC_CTL_HMACEN_Pos) /*!< CRPT_T::HMAC_CTL: HMACEN Mask */ + +#define CRPT_HMAC_CTL_DMALAST_Pos (5) /*!< CRPT_T::HMAC_CTL: DMALAST Position */ +#define CRPT_HMAC_CTL_DMALAST_Msk (0x1ul << CRPT_HMAC_CTL_DMALAST_Pos) /*!< CRPT_T::HMAC_CTL: DMALAST Mask */ + +#define CRPT_HMAC_CTL_DMAEN_Pos (7) /*!< CRPT_T::HMAC_CTL: DMAEN Position */ +#define CRPT_HMAC_CTL_DMAEN_Msk (0x1ul << CRPT_HMAC_CTL_DMAEN_Pos) /*!< CRPT_T::HMAC_CTL: DMAEN Mask */ + +#define CRPT_HMAC_CTL_OPMODE_Pos (8) /*!< CRPT_T::HMAC_CTL: OPMODE Position */ +#define CRPT_HMAC_CTL_OPMODE_Msk (0x7ul << CRPT_HMAC_CTL_OPMODE_Pos) /*!< CRPT_T::HMAC_CTL: OPMODE Mask */ + +#define CRPT_HMAC_CTL_OUTSWAP_Pos (22) /*!< CRPT_T::HMAC_CTL: OUTSWAP Position */ +#define CRPT_HMAC_CTL_OUTSWAP_Msk (0x1ul << CRPT_HMAC_CTL_OUTSWAP_Pos) /*!< CRPT_T::HMAC_CTL: OUTSWAP Mask */ + +#define CRPT_HMAC_CTL_INSWAP_Pos (23) /*!< CRPT_T::HMAC_CTL: INSWAP Position */ +#define CRPT_HMAC_CTL_INSWAP_Msk (0x1ul << CRPT_HMAC_CTL_INSWAP_Pos) /*!< CRPT_T::HMAC_CTL: INSWAP Mask */ + +#define CRPT_HMAC_STS_BUSY_Pos (0) /*!< CRPT_T::HMAC_STS: BUSY Position */ +#define CRPT_HMAC_STS_BUSY_Msk (0x1ul << CRPT_HMAC_STS_BUSY_Pos) /*!< CRPT_T::HMAC_STS: BUSY Mask */ + +#define CRPT_HMAC_STS_DMABUSY_Pos (1) /*!< CRPT_T::HMAC_STS: DMABUSY Position */ +#define CRPT_HMAC_STS_DMABUSY_Msk (0x1ul << CRPT_HMAC_STS_DMABUSY_Pos) /*!< CRPT_T::HMAC_STS: DMABUSY Mask */ + +#define CRPT_HMAC_STS_DMAERR_Pos (8) /*!< CRPT_T::HMAC_STS: DMAERR Position */ +#define CRPT_HMAC_STS_DMAERR_Msk (0x1ul << CRPT_HMAC_STS_DMAERR_Pos) /*!< CRPT_T::HMAC_STS: DMAERR Mask */ + +#define CRPT_HMAC_STS_DATINREQ_Pos (16) /*!< CRPT_T::HMAC_STS: DATINREQ Position */ +#define CRPT_HMAC_STS_DATINREQ_Msk (0x1ul << CRPT_HMAC_STS_DATINREQ_Pos) /*!< CRPT_T::HMAC_STS: DATINREQ Mask */ + +#define CRPT_HMAC_DGSTx_DGST_Pos (0) /*!< CRPT_T::HMAC_DGST[16]: DGST Position */ +#define CRPT_HMAC_DGSTx_DGST_Msk (0xfffffffful << CRPT_HMAC_DGSTx_DGST_Pos) /*!< CRPT_T::HMAC_DGST[16]: DGST Mask */ + +#define CRPT_HMAC_KEYCNT_KEYCNT_Pos (0) /*!< CRPT_T::HMAC_KEYCNT: KEYCNT Position */ +#define CRPT_HMAC_KEYCNT_KEYCNT_Msk (0xfffffffful << CRPT_HMAC_KEYCNT_KEYCNT_Pos) /*!< CRPT_T::HMAC_KEYCNT: KEYCNT Mask */ + +#define CRPT_HMAC_SADDR_SADDR_Pos (0) /*!< CRPT_T::HMAC_SADDR: SADDR Position */ +#define CRPT_HMAC_SADDR_SADDR_Msk (0xfffffffful << CRPT_HMAC_SADDR_SADDR_Pos) /*!< CRPT_T::HMAC_SADDR: SADDR Mask */ + +#define CRPT_HMAC_DMACNT_DMACNT_Pos (0) /*!< CRPT_T::HMAC_DMACNT: DMACNT Position */ +#define CRPT_HMAC_DMACNT_DMACNT_Msk (0xfffffffful << CRPT_HMAC_DMACNT_DMACNT_Pos) /*!< CRPT_T::HMAC_DMACNT: DMACNT Mask */ + +#define CRPT_HMAC_DATIN_DATIN_Pos (0) /*!< CRPT_T::HMAC_DATIN: DATIN Position */ +#define CRPT_HMAC_DATIN_DATIN_Msk (0xfffffffful << CRPT_HMAC_DATIN_DATIN_Pos) /*!< CRPT_T::HMAC_DATIN: DATIN Mask */ + +#define CRPT_ECC_CTL_START_Pos (0) /*!< CRPT_T::ECC_CTL: START Position */ +#define CRPT_ECC_CTL_START_Msk (0x1ul << CRPT_ECC_CTL_START_Pos) /*!< CRPT_T::ECC_CTL: START Mask */ + +#define CRPT_ECC_CTL_STOP_Pos (1) /*!< CRPT_T::ECC_CTL: STOP Position */ +#define CRPT_ECC_CTL_STOP_Msk (0x1ul << CRPT_ECC_CTL_STOP_Pos) /*!< CRPT_T::ECC_CTL: STOP Mask */ + +#define CRPT_ECC_CTL_DMAEN_Pos (7) /*!< CRPT_T::ECC_CTL: DMAEN Position */ +#define CRPT_ECC_CTL_DMAEN_Msk (0x1ul << CRPT_ECC_CTL_DMAEN_Pos) /*!< CRPT_T::ECC_CTL: DMAEN Mask */ + +#define CRPT_ECC_CTL_FSEL_Pos (8) /*!< CRPT_T::ECC_CTL: FSEL Position */ +#define CRPT_ECC_CTL_FSEL_Msk (0x1ul << CRPT_ECC_CTL_FSEL_Pos) /*!< CRPT_T::ECC_CTL: FSEL Mask */ + +#define CRPT_ECC_CTL_ECCOP_Pos (9) /*!< CRPT_T::ECC_CTL: ECCOP Position */ +#define CRPT_ECC_CTL_ECCOP_Msk (0x3ul << CRPT_ECC_CTL_ECCOP_Pos) /*!< CRPT_T::ECC_CTL: ECCOP Mask */ + +#define CRPT_ECC_CTL_MODOP_Pos (11) /*!< CRPT_T::ECC_CTL: MODOP Position */ +#define CRPT_ECC_CTL_MODOP_Msk (0x3ul << CRPT_ECC_CTL_MODOP_Pos) /*!< CRPT_T::ECC_CTL: MODOP Mask */ + +#define CRPT_ECC_CTL_LDP1_Pos (16) /*!< CRPT_T::ECC_CTL: LDP1 Position */ +#define CRPT_ECC_CTL_LDP1_Msk (0x1ul << CRPT_ECC_CTL_LDP1_Pos) /*!< CRPT_T::ECC_CTL: LDP1 Mask */ + +#define CRPT_ECC_CTL_LDP2_Pos (17) /*!< CRPT_T::ECC_CTL: LDP2 Position */ +#define CRPT_ECC_CTL_LDP2_Msk (0x1ul << CRPT_ECC_CTL_LDP2_Pos) /*!< CRPT_T::ECC_CTL: LDP2 Mask */ + +#define CRPT_ECC_CTL_LDA_Pos (18) /*!< CRPT_T::ECC_CTL: LDA Position */ +#define CRPT_ECC_CTL_LDA_Msk (0x1ul << CRPT_ECC_CTL_LDA_Pos) /*!< CRPT_T::ECC_CTL: LDA Mask */ + +#define CRPT_ECC_CTL_LDB_Pos (19) /*!< CRPT_T::ECC_CTL: LDB Position */ +#define CRPT_ECC_CTL_LDB_Msk (0x1ul << CRPT_ECC_CTL_LDB_Pos) /*!< CRPT_T::ECC_CTL: LDB Mask */ + +#define CRPT_ECC_CTL_LDN_Pos (20) /*!< CRPT_T::ECC_CTL: LDN Position */ +#define CRPT_ECC_CTL_LDN_Msk (0x1ul << CRPT_ECC_CTL_LDN_Pos) /*!< CRPT_T::ECC_CTL: LDN Mask */ + +#define CRPT_ECC_CTL_LDK_Pos (21) /*!< CRPT_T::ECC_CTL: LDK Position */ +#define CRPT_ECC_CTL_LDK_Msk (0x1ul << CRPT_ECC_CTL_LDK_Pos) /*!< CRPT_T::ECC_CTL: LDK Mask */ + +#define CRPT_ECC_CTL_CURVEM_Pos (22) /*!< CRPT_T::ECC_CTL: CURVEM Position */ +#define CRPT_ECC_CTL_CURVEM_Msk (0x3fful << CRPT_ECC_CTL_CURVEM_Pos) /*!< CRPT_T::ECC_CTL: CURVEM Mask */ + +#define CRPT_ECC_STS_BUSY_Pos (0) /*!< CRPT_T::ECC_STS: BUSY Position */ +#define CRPT_ECC_STS_BUSY_Msk (0x1ul << CRPT_ECC_STS_BUSY_Pos) /*!< CRPT_T::ECC_STS: BUSY Mask */ + +#define CRPT_ECC_STS_DMABUSY_Pos (1) /*!< CRPT_T::ECC_STS: DMABUSY Position */ +#define CRPT_ECC_STS_DMABUSY_Msk (0x1ul << CRPT_ECC_STS_DMABUSY_Pos) /*!< CRPT_T::ECC_STS: DMABUSY Mask */ + +#define CRPT_ECC_STS_BUSERR_Pos (16) /*!< CRPT_T::ECC_STS: BUSERR Position */ +#define CRPT_ECC_STS_BUSERR_Msk (0x1ul << CRPT_ECC_STS_BUSERR_Pos) /*!< CRPT_T::ECC_STS: BUSERR Mask */ + +#define CRPT_ECC_X1_POINTX1_Pos (0) /*!< CRPT_T::ECC_X1[18]: POINTX1 Position */ +#define CRPT_ECC_X1_POINTX1_Msk (0xfffffffful << CRPT_ECC_X1_POINTX1_Pos) /*!< CRPT_T::ECC_X1[18]: POINTX1 Mask */ + +#define CRPT_ECC_Y1_POINTY1_Pos (0) /*!< CRPT_T::ECC_Y1[18]: POINTY1 Position */ +#define CRPT_ECC_Y1_POINTY1_Msk (0xfffffffful << CRPT_ECC_Y1_POINTY1_Pos) /*!< CRPT_T::ECC_Y1[18]: POINTY1 Mask */ + +#define CRPT_ECC_X2_POINTX2_Pos (0) /*!< CRPT_T::ECC_X2[18]: POINTX2 Position */ +#define CRPT_ECC_X2_POINTX2_Msk (0xfffffffful << CRPT_ECC_X2_POINTX2_Pos) /*!< CRPT_T::ECC_X2[18]: POINTX2 Mask */ + +#define CRPT_ECC_Y2_POINTY2_Pos (0) /*!< CRPT_T::ECC_Y2[18]: POINTY2 Position */ +#define CRPT_ECC_Y2_POINTY2_Msk (0xfffffffful << CRPT_ECC_Y2_POINTY2_Pos) /*!< CRPT_T::ECC_Y2[18]: POINTY2 Mask */ + +#define CRPT_ECC_A_CURVEA_Pos (0) /*!< CRPT_T::ECC_A[18]: CURVEA Position */ +#define CRPT_ECC_A_CURVEA_Msk (0xfffffffful << CRPT_ECC_A_CURVEA_Pos) /*!< CRPT_T::ECC_A[18]: CURVEA Mask */ + +#define CRPT_ECC_B_CURVEB_Pos (0) /*!< CRPT_T::ECC_B[18]: CURVEB Position */ +#define CRPT_ECC_B_CURVEB_Msk (0xfffffffful << CRPT_ECC_B_CURVEB_Pos) /*!< CRPT_T::ECC_B[18]: CURVEB Mask */ + +#define CRPT_ECC_N_CURVEN_Pos (0) /*!< CRPT_T::ECC_N[18]: CURVEN Position */ +#define CRPT_ECC_N_CURVEN_Msk (0xfffffffful << CRPT_ECC_N_CURVEN_Pos) /*!< CRPT_T::ECC_N[18]: CURVEN Mask */ + +#define CRPT_ECC_K_SCALARK_Pos (0) /*!< CRPT_T::ECC_K[18]: SCALARK Position */ +#define CRPT_ECC_K_SCALARK_Msk (0xfffffffful << CRPT_ECC_K_SCALARK_Pos) /*!< CRPT_T::ECC_K[18]: SCALARK Mask */ + +#define CRPT_ECC_DADDR_DADDR_Pos (0) /*!< CRPT_T::ECC_DADDR: DADDR Position */ +#define CRPT_ECC_DADDR_DADDR_Msk (0xfffffffful << CRPT_ECC_DADDR_DADDR_Pos) /*!< CRPT_T::ECC_DADDR: DADDR Mask */ + +#define CRPT_ECC_STARTREG_STARTREG_Pos (0) /*!< CRPT_T::ECC_STARTREG: STARTREG Position*/ +#define CRPT_ECC_STARTREG_STARTREG_Msk (0xfffffffful << CRPT_ECC_STARTREG_STARTREG_Pos) /*!< CRPT_T::ECC_STARTREG: STARTREG Mask */ + +#define CRPT_ECC_WORDCNT_WORDCNT_Pos (0) /*!< CRPT_T::ECC_WORDCNT: WORDCNT Position */ +#define CRPT_ECC_WORDCNT_WORDCNT_Msk (0xfffffffful << CRPT_ECC_WORDCNT_WORDCNT_Pos) /*!< CRPT_T::ECC_WORDCNT: WORDCNT Mask */ + +#define CRPT_RSA_CTL_START_Pos (0) /*!< CRPT RSA_CTL: START Position */ +#define CRPT_RSA_CTL_START_Msk (0x1ul << CRPT_RSA_CTL_START_Pos) /*!< CRPT RSA_CTL: START Mask */ + +#define CRPT_RSA_CTL_STOP_Pos (1) /*!< CRPT RSA_CTL: STOP Position */ +#define CRPT_RSA_CTL_STOP_Msk (0x1ul << CRPT_RSA_CTL_STOP_Pos) /*!< CRPT RSA_CTL: STOP Mask */ + +#define CRPT_RSA_CTL_DMAEN_Pos (7) /*!< CRPT RSA_CTL: DMAEN Position */ +#define CRPT_RSA_CTL_DMAEN_Msk (0x1ul << CRPT_RSA_CTL_DMAEN_Pos) /*!< CRPT RSA_CTL: DMAEN Mask */ + +#define CRPT_RSA_CTL_LDM_Pos (8) /*!< CRPT RSA_CTL: LDM Position */ +#define CRPT_RSA_CTL_LDM_Msk (0x1ul << CRPT_RSA_CTL_LDM_Pos) /*!< CRPT RSA_CTL: LDM Mask */ + +#define CRPT_RSA_CTL_LDE_Pos (9) /*!< CRPT RSA_CTL: LDE Position */ +#define CRPT_RSA_CTL_LDE_Msk (0x1ul << CRPT_RSA_CTL_LDE_Pos) /*!< CRPT RSA_CTL: LDE Mask */ + +#define CRPT_RSA_CTL_LDN_Pos (10) /*!< CRPT RSA_CTL: LDN Position */ +#define CRPT_RSA_CTL_LDN_Msk (0x1ul << CRPT_RSA_CTL_LDN_Pos) /*!< CRPT RSA_CTL: LDN Mask */ + +#define CRPT_RSA_CTL_LDC_Pos (11) /*!< CRPT RSA_CTL: LDC Position */ +#define CRPT_RSA_CTL_LDC_Msk (0x1ul << CRPT_RSA_CTL_LDC_Pos) /*!< CRPT RSA_CTL: LDC Mask */ + +#define CRPT_RSA_CTL_KEYLEN_Pos (16) /*!< CRPT RSA_CTL: KEYLEN Position */ +#define CRPT_RSA_CTL_KEYLEN_Msk (0x1FFFul << CRPT_RSA_CTL_KEYLEN_Pos) /*!< CRPT RSA_CTL: KEYLEN Mask */ + +#define CRPT_RSA_STS_BUSY_Pos (0) /*!< CRPT RSA_STS: BUSY Position */ +#define CRPT_RSA_STS_BUSY_Msk (0x1ul << CRPT_RSA_STS_BUSY_Pos) /*!< CRPT RSA_STS: BUSY Mask */ + +#define CRPT_RSA_STS_DMABUSY_Pos (1) /*!< CRPT RSA_STS: DMABUSY Position */ +#define CRPT_RSA_STS_DMABUSY_Msk (0x1ul << CRPT_RSA_STS_DMABUSY_Pos) /*!< CRPT RSA_STS: DMABUSY Mask */ + +#define CRPT_RSA_STS_BUSERR_Pos (16) /*!< CRPT ECC_RSA: BUSERR Position */ +#define CRPT_RSA_STS_BUSERR_Msk (0x1ul << CRPT_RSA_STS_BUSERR_Pos) /*!< CRPT ECC_RSA: BUSERR Mask */ + + +/**@}*/ /* CRPT_CONST CRYPTO */ + +/**@}*/ /* end of CRYPTO register group */ + + +/** @addtogroup CRYPTO_EXPORTED_CONSTANTS CRYPTO Exported Constants + @{ +*/ + +#define PRNG_KEY_SIZE_64 0UL /*!< Select to generate 64-bit random key \hideinitializer */ +#define PRNG_KEY_SIZE_128 1UL /*!< Select to generate 128-bit random key \hideinitializer */ +#define PRNG_KEY_SIZE_192 2UL /*!< Select to generate 192-bit random key \hideinitializer */ +#define PRNG_KEY_SIZE_256 3UL /*!< Select to generate 256-bit random key \hideinitializer */ + +#define PRNG_SEED_CONT 0UL /*!< PRNG using current seed \hideinitializer */ +#define PRNG_SEED_RELOAD 1UL /*!< PRNG reload new seed \hideinitializer */ + +#define AES_KEY_SIZE_128 0UL /*!< AES select 128-bit key length \hideinitializer */ +#define AES_KEY_SIZE_192 1UL /*!< AES select 192-bit key length \hideinitializer */ +#define AES_KEY_SIZE_256 2UL /*!< AES select 256-bit key length \hideinitializer */ + +#define AES_MODE_ECB 0UL /*!< AES select ECB mode \hideinitializer */ +#define AES_MODE_CBC 1UL /*!< AES select CBC mode \hideinitializer */ +#define AES_MODE_CFB 2UL /*!< AES select CFB mode \hideinitializer */ +#define AES_MODE_OFB 3UL /*!< AES select OFB mode \hideinitializer */ +#define AES_MODE_CTR 4UL /*!< AES select CTR mode \hideinitializer */ +#define AES_MODE_CBC_CS1 0x10UL /*!< AES select CBC CS1 mode \hideinitializer */ +#define AES_MODE_CBC_CS2 0x11UL /*!< AES select CBC CS2 mode \hideinitializer */ +#define AES_MODE_CBC_CS3 0x12UL /*!< AES select CBC CS3 mode \hideinitializer */ + +#define AES_NO_SWAP 0UL /*!< AES do not swap input and output data \hideinitializer */ +#define AES_OUT_SWAP 1UL /*!< AES swap output data \hideinitializer */ +#define AES_IN_SWAP 2UL /*!< AES swap input data \hideinitializer */ +#define AES_IN_OUT_SWAP 3UL /*!< AES swap both input and output data \hideinitializer */ + +#define SHA_MODE_SHA1 0UL /*!< SHA select SHA-1 160-bit \hideinitializer */ +#define SHA_MODE_SHA224 5UL /*!< SHA select SHA-224 224-bit \hideinitializer */ +#define SHA_MODE_SHA256 4UL /*!< SHA select SHA-256 256-bit \hideinitializer */ +#define SHA_MODE_SHA384 7UL /*!< SHA select SHA-384 384-bit \hideinitializer */ +#define SHA_MODE_SHA512 6UL /*!< SHA select SHA-512 512-bit \hideinitializer */ + +#define SHA_NO_SWAP 0UL /*!< SHA do not swap input and output data \hideinitializer */ +#define SHA_OUT_SWAP 1UL /*!< SHA swap output data \hideinitializer */ +#define SHA_IN_SWAP 2UL /*!< SHA swap input data \hideinitializer */ +#define SHA_IN_OUT_SWAP 3UL /*!< SHA swap both input and output data \hideinitializer */ + +#define CRYPTO_DMA_FIRST 0x4UL /*!< Do first encrypt/decrypt in DMA cascade \hideinitializer */ +#define CRYPTO_DMA_ONE_SHOT 0x5UL /*!< Do one shot encrypt/decrypt with DMA \hideinitializer */ +#define CRYPTO_DMA_CONTINUE 0x6UL /*!< Do continuous encrypt/decrypt in DMA cascade \hideinitializer */ +#define CRYPTO_DMA_LAST 0x7UL /*!< Do last encrypt/decrypt in DMA cascade \hideinitializer */ + +typedef enum +{ + /*!< ECC curve \hideinitializer */ + CURVE_P_192, /*!< ECC curve P-192 \hideinitializer */ + CURVE_P_224, /*!< ECC curve P-224 \hideinitializer */ + CURVE_P_256, /*!< ECC curve P-256 \hideinitializer */ + CURVE_P_384, /*!< ECC curve P-384 \hideinitializer */ + CURVE_P_521, /*!< ECC curve P-521 \hideinitializer */ + CURVE_K_163, /*!< ECC curve K-163 \hideinitializer */ + CURVE_K_233, /*!< ECC curve K-233 \hideinitializer */ + CURVE_K_283, /*!< ECC curve K-283 \hideinitializer */ + CURVE_K_409, /*!< ECC curve K-409 \hideinitializer */ + CURVE_K_571, /*!< ECC curve K-571 \hideinitializer */ + CURVE_B_163, /*!< ECC curve B-163 \hideinitializer */ + CURVE_B_233, /*!< ECC curve B-233 \hideinitializer */ + CURVE_B_283, /*!< ECC curve B-283 \hideinitializer */ + CURVE_B_409, /*!< ECC curve B-409 \hideinitializer */ + CURVE_B_571, /*!< ECC curve K-571 \hideinitializer */ + CURVE_KO_192, /*!< ECC 192-bits "Koblitz" curve \hideinitializer */ + CURVE_KO_224, /*!< ECC 224-bits "Koblitz" curve \hideinitializer */ + CURVE_KO_256, /*!< ECC 256-bits "Koblitz" curve \hideinitializer */ + CURVE_BP_256, /*!< ECC Brainpool 256-bits curve \hideinitializer */ + CURVE_BP_384, /*!< ECC Brainpool 256-bits curve \hideinitializer */ + CURVE_BP_512, /*!< ECC Brainpool 256-bits curve \hideinitializer */ + CURVE_UNDEF, /*!< Invalid curve \hideinitializer */ +} +E_ECC_CURVE; /*!< ECC curve \hideinitializer */ + + +#define RSA_MAX_KLEN (2048) +#define RSA_KBUF_HLEN (RSA_MAX_KLEN/4 + 8) +#define RSA_KBUF_BLEN (RSA_MAX_KLEN + 32) + + +/*@}*/ /* end of group CRYPTO_EXPORTED_CONSTANTS */ + + +/** @addtogroup CRYPTO_EXPORTED_MACROS CRYPTO Exported Macros + @{ +*/ + +/*----------------------------------------------------------------------------------------------*/ +/* Macros */ +/*----------------------------------------------------------------------------------------------*/ + +/** + * @brief This macro enables PRNG interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define PRNG_ENABLE_INT(crpt) ((crpt)->INTEN |= CRPT_INTEN_PRNGIEN_Msk) + +/** + * @brief This macro disables PRNG interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define PRNG_DISABLE_INT(crpt) ((crpt)->INTEN &= ~CRPT_INTEN_PRNGIEN_Msk) + +/** + * @brief This macro gets PRNG interrupt flag. + * @param crpt Specified cripto module + * @return PRNG interrupt flag. + * \hideinitializer + */ +#define PRNG_GET_INT_FLAG(crpt) ((crpt)->INTSTS & CRPT_INTSTS_PRNGIF_Msk) + +/** + * @brief This macro clears PRNG interrupt flag. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define PRNG_CLR_INT_FLAG(crpt) ((crpt)->INTSTS = CRPT_INTSTS_PRNGIF_Msk) + +/** + * @brief This macro enables AES interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define AES_ENABLE_INT(crpt) ((crpt)->INTEN |= (CRPT_INTEN_AESIEN_Msk|CRPT_INTEN_AESEIEN_Msk)) + +/** + * @brief This macro disables AES interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define AES_DISABLE_INT(crpt) ((crpt)->INTEN &= ~(CRPT_INTEN_AESIEN_Msk|CRPT_INTEN_AESEIEN_Msk)) + +/** + * @brief This macro gets AES interrupt flag. + * @param crpt Specified cripto module + * @return AES interrupt flag. + * \hideinitializer + */ +#define AES_GET_INT_FLAG(crpt) ((crpt)->INTSTS & (CRPT_INTSTS_AESIF_Msk|CRPT_INTSTS_AESEIF_Msk)) + +/** + * @brief This macro clears AES interrupt flag. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define AES_CLR_INT_FLAG(crpt) ((crpt)->INTSTS = (CRPT_INTSTS_AESIF_Msk|CRPT_INTSTS_AESEIF_Msk)) + +/** + * @brief This macro enables AES key protection. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define AES_ENABLE_KEY_PROTECT(crpt) ((crpt)->AES_CTL |= CRPT_AES_CTL_KEYPRT_Msk) + +/** + * @brief This macro disables AES key protection. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define AES_DISABLE_KEY_PROTECT(crpt) ((crpt)->AES_CTL = ((crpt)->AES_CTL & ~CRPT_AES_CTL_KEYPRT_Msk) | (0x16UL<AES_CTL &= ~CRPT_AES_CTL_KEYPRT_Msk) + +/** + * @brief This macro enables SHA interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define SHA_ENABLE_INT(crpt) ((crpt)->INTEN |= (CRPT_INTEN_HMACIEN_Msk|CRPT_INTEN_HMACEIEN_Msk)) + +/** + * @brief This macro disables SHA interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define SHA_DISABLE_INT(crpt) ((crpt)->INTEN &= ~(CRPT_INTEN_HMACIEN_Msk|CRPT_INTEN_HMACEIEN_Msk)) + +/** + * @brief This macro gets SHA interrupt flag. + * @param crpt Specified cripto module + * @return SHA interrupt flag. + * \hideinitializer + */ +#define SHA_GET_INT_FLAG(crpt) ((crpt)->INTSTS & (CRPT_INTSTS_HMACIF_Msk|CRPT_INTSTS_HMACEIF_Msk)) + +/** + * @brief This macro clears SHA interrupt flag. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define SHA_CLR_INT_FLAG(crpt) ((crpt)->INTSTS = (CRPT_INTSTS_HMACIF_Msk|CRPT_INTSTS_HMACEIF_Msk)) + +/** + * @brief This macro enables ECC interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define ECC_ENABLE_INT(crpt) ((crpt)->INTEN |= (CRPT_INTEN_ECCIEN_Msk|CRPT_INTEN_ECCEIEN_Msk)) + +/** + * @brief This macro disables ECC interrupt. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define ECC_DISABLE_INT(crpt) ((crpt)->INTEN &= ~(CRPT_INTEN_ECCIEN_Msk|CRPT_INTEN_ECCEIEN_Msk)) + +/** + * @brief This macro gets ECC interrupt flag. + * @param crpt Specified cripto module + * @return ECC interrupt flag. + * \hideinitializer + */ +#define ECC_GET_INT_FLAG(crpt) ((crpt)->INTSTS & (CRPT_INTSTS_ECCIF_Msk|CRPT_INTSTS_ECCEIF_Msk)) + +/** + * @brief This macro clears ECC interrupt flag. + * @param crpt Specified cripto module + * @return None + * \hideinitializer + */ +#define ECC_CLR_INT_FLAG(crpt) ((crpt)->INTSTS = (CRPT_INTSTS_ECCIF_Msk|CRPT_INTSTS_ECCEIF_Msk)) + + +/*@}*/ /* end of group CRYPTO_EXPORTED_MACROS */ + + +/** @addtogroup CRYPTO_EXPORTED_FUNCTIONS CRYPTO Exported Functions + @{ +*/ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Functions */ +/*---------------------------------------------------------------------------------------------------------*/ + +void PRNG_Open(CRPT_T *crpt, uint32_t u32KeySize, uint32_t u32SeedReload, uint32_t u32Seed); +void PRNG_Start(CRPT_T *crpt); +void PRNG_Read(CRPT_T *crpt, uint32_t u32RandKey[]); +void AES_Open(CRPT_T *crpt, uint32_t u32EncDec, uint32_t u32OpMode, uint32_t u32KeySize, uint32_t u32SwapType); +void AES_Start(CRPT_T *crpt, uint32_t u32DMAMode); +void AES_SetKey(CRPT_T *crpt, uint32_t au32Keys[], uint32_t u32KeySize); +void AES_SetInitVect(CRPT_T *crpt, uint32_t au32IV[]); +void AES_SetDMATransfer(CRPT_T *crpt, uint32_t u32SrcAddr, uint32_t u32DstAddr, uint32_t u32TransCnt); +void SHA_Open(CRPT_T *crpt, uint32_t u32OpMode, uint32_t u32SwapType, uint32_t hmac_key_len); +void SHA_Start(CRPT_T *crpt, uint32_t u32DMAMode); +void SHA_SetDMATransfer(CRPT_T *crpt, uint32_t u32SrcAddr, uint32_t u32TransCnt); +void SHA_Read(CRPT_T *crpt, uint32_t u32Digest[]); +void ECC_Complete(CRPT_T *crpt); +int ECC_IsPrivateKeyValid(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char private_k[]); +int32_t ECC_GeneratePublicKey(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *private_k, char public_k1[], char public_k2[]); +int32_t ECC_Mutiply(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char x1[], char y1[], char *k, char x2[], char y2[]); +int32_t ECC_GenerateSecretZ(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *private_k, char public_k1[], char public_k2[], char secret_z[]); +int32_t ECC_GenerateSignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, char *d, char *k, char *R, char *S); +int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, char *public_k1, char *public_k2, char *R, char *S); +void RSA_Calculate_C(int rsa_len, char *n, char *C); +int32_t RSA_GenerateSignature(CRPT_T *crpt, int rsa_len, char *n, char *d, char *C, char *msg, char *sig); +int32_t RSA_VerifySignature(CRPT_T *crpt, int rsa_len, char *n, char *e, char *C, char *sig, char *msg); + + +/*@}*/ /* end of group CRYPTO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group Crypto_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_CRYPTO_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_ebi.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_ebi.h new file mode 100644 index 0000000000..fa5c5e5f8e --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_ebi.h @@ -0,0 +1,418 @@ +/**************************************************************************//** + * @file ebi.h + * @brief 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 + +#include "nuc980.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup EBI_Driver EBI Driver + @{ +*/ + +/** @addtogroup EBI_EXPORTED_CONSTANTS EBI Exported Constants + @{ +*/ + +#define EBI ((EBI_T *) EBI_BA) + +/*---------------------- External Bus Interface Controller -------------------------*/ +/** + @addtogroup EBI External Bus Interface Controller(EBI) + Memory Mapped Structure for EBI Controller +@{ */ + + +typedef struct +{ + + __IO uint32_t CTL0; /* Offset: 0x00 External Bus Interface Bank0 Control Register */ + __IO uint32_t TCTL0; /* Offset: 0x04 External Bus Interface Bank0 Timing Control Register */ + __I uint32_t RESERVE0[2]; + __IO uint32_t CTL1; /* Offset: 0x10 External Bus Interface Bank1 Control Register */ + __IO uint32_t TCTL1; /* Offset: 0x14 External Bus Interface Bank1 Timing Control Register */ + __I uint32_t RESERVE1[2]; + __IO uint32_t CTL2; /* Offset: 0x20 External Bus Interface Bank1 Control Register */ + __IO uint32_t TCTL2; /* Offset: 0x24 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::CTL: EN Position \hideinitializer */ +#define EBI_CTL_EN_Msk (0x1ul << EBI_CTL_EN_Pos) /*!< EBI_T::CTL: EN Mask \hideinitializer */ + +#define EBI_CTL_DW16_Pos (1) /*!< EBI_T::CTL: DW16 Position \hideinitializer */ +#define EBI_CTL_DW16_Msk (0x1ul << EBI_CTL_DW16_Pos) /*!< EBI_T::CTL: DW16 Mask \hideinitializer */ + +#define EBI_CTL_CSPOLINV_Pos (2) /*!< EBI_T::CTL: CSPOLINV Position \hideinitializer */ +#define EBI_CTL_CSPOLINV_Msk (0x1ul << EBI_CTL_CSPOLINV_Pos) /*!< EBI_T::CTL: CSPOLINV Mask \hideinitializer */ + +#define EBI_CTL_CACCESS_Pos (4) /*!< EBI EBICON: CS_PINV Position \hideinitializer */ +#define EBI_CTL_CACCESS_Msk (1ul << EBI_CTL_CACCESS_Pos) /*!< EBI EBICON: CS_PINV Mask \hideinitializer */ + +#define EBI_CTL_MCLKDIV_Pos (8) /*!< EBI_T::CTL: MCLKDIV Position \hideinitializer */ +#define EBI_CTL_MCLKDIV_Msk (0x7ul << EBI_CTL_MCLKDIV_Pos) /*!< EBI_T::CTL: MCLKDIV Mask \hideinitializer */ + +#define EBI_CTL_WBUFEN_Pos (24) /*!< EBI_T::CTL: WBUFEN Position \hideinitializer */ +#define EBI_CTL_WBUFEN_Msk (0x1ul << EBI_CTL_WBUFEN_Pos) /*!< EBI_T::CTL: WBUFEN Mask \hideinitializer */ + +#define EBI_TCTL_TACC_Pos (3) /*!< EBI_T::TCTL: TACC Position \hideinitializer */ +#define EBI_TCTL_TACC_Msk (0x1ful << EBI_TCTL_TACC_Pos) /*!< EBI_T::TCTL: TACC Mask \hideinitializer */ + +#define EBI_TCTL_TAHD_Pos (8) /*!< EBI_T::TCTL: TAHD Position \hideinitializer */ +#define EBI_TCTL_TAHD_Msk (0x7ul << EBI_TCTL_TAHD_Pos) /*!< EBI_T::TCTL: TAHD Mask \hideinitializer */ + +#define EBI_TCTL_W2X_Pos (12) /*!< EBI_T::TCTL: W2X Position \hideinitializer */ +#define EBI_TCTL_W2X_Msk (0xful << EBI_TCTL_W2X_Pos) /*!< EBI_T::TCTL: W2X Mask \hideinitializer */ + +#define EBI_TCTL_RAHDOFF_Pos (22) /*!< EBI_T::TCTL: RAHDOFF Position \hideinitializer */ +#define EBI_TCTL_RAHDOFF_Msk (0x1ul << EBI_TCTL_RAHDOFF_Pos) /*!< EBI_T::TCTL: RAHDOFF Mask \hideinitializer */ + +#define EBI_TCTL_WAHDOFF_Pos (23) /*!< EBI_T::TCTL: WAHDOFF Position \hideinitializer */ +#define EBI_TCTL_WAHDOFF_Msk (0x1ul << EBI_TCTL_WAHDOFF_Pos) /*!< EBI_T::TCTL: WAHDOFF Mask \hideinitializer */ + +#define EBI_TCTL_R2R_Pos (24) /*!< EBI_T::TCTL: R2R Position \hideinitializer */ +#define EBI_TCTL_R2R_Msk (0xful << EBI_TCTL_R2R_Pos) /*!< EBI_T::TCTL: R2R Mask \hideinitializer */ + +/**@}*/ /* EBI_CONST */ +/**@}*/ /* end of EBI register group */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* 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_BANK2_BASE_ADDR 0x60200000UL /*!< EBI bank2 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 */ +#define EBI_BANK2 2UL /*!< EBI bank 2 \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_MCLKDIV_64 0x6UL /*!< EBI output clock(MCLK) is HCLK/64 \hideinitializer */ +#define EBI_MCLKDIV_128 0x7UL /*!< EBI output clock(MCLK) is HCLK/128 \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 (0x1UL << 4) /*!< 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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#define EBI1_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 8-bit data on EBI bank2 + * + * @param[in] u32Addr The data address on EBI bank2. + * + * @return 8-bit Data + * + * @details This macro is used to read 8-bit data from specify address on EBI bank2. + * \hideinitializer + */ +#define EBI2_READ_DATA8(u32Addr) (*((volatile unsigned char *)(EBI_BANK2_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 8-bit data to EBI bank2 + * + * @param[in] u32Addr The data address on EBI bank2. + * @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 bank2. + * \hideinitializer + */ +#define EBI2_WRITE_DATA8(u32Addr, u32Data) (*((volatile unsigned char *)(EBI_BANK2_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 16-bit data on EBI bank2 + * + * @param[in] u32Addr The data address on EBI bank2. + * + * @return 16-bit Data + * + * @details This macro is used to read 16-bit data from specify address on EBI bank2. + * \hideinitializer + */ +#define EBI2_READ_DATA16(u32Addr) (*((volatile unsigned short *)(EBI_BANK2_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 16-bit data to EBI bank2 + * + * @param[in] u32Addr The data address on EBI bank2. + * @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 bank2. + * \hideinitializer + */ +#define EBI2_WRITE_DATA16(u32Addr, u32Data) (*((volatile unsigned short *)(EBI_BANK2_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 32-bit data on EBI bank2 + * + * @param[in] u32Addr The data address on EBI bank2. + * + * @return 32-bit Data + * + * @details This macro is used to read 32-bit data from specify address on EBI bank2. + * \hideinitializer + */ +#define EBI2_READ_DATA32(u32Addr) (*((volatile unsigned int *)(EBI_BANK2_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 32-bit data to EBI bank2 + * + * @param[in] u32Addr The data address on EBI bank2. + * @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 bank2. + * \hideinitializer + */ +#define EBI2_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK2_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Enable EBI Write Buffer + * + * @return None + * + * @details This macro is used to improve EBI write operation for EBI all banks. + * \hideinitializer + */ +#define EBI_ENABLE_WRITE_BUFFER() outpw(REG_EBI_CTL0, inpw(REG_EBI_CTL0) | (0x1UL << 24)) + + +/** + * @brief Disable EBI Write Buffer + * + * @return None + * + * @details This macro is used to disable EBI write buffer function. + * \hideinitializer + */ +#define EBI_DISABLE_WRITE_BUFFER() outpw(REG_EBI_CTL0, (inpw(REG_EBI_CTL0) & ~(0x1UL << 24)) | (0x1UL << 24)) + +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 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_emac.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_emac.h new file mode 100644 index 0000000000..f6a5ce86e9 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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/nuc980/Driver/Include/nu_etimer.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_etimer.h new file mode 100644 index 0000000000..d23e0321a1 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_etimer.h @@ -0,0 +1,869 @@ +/**************************************************************************//** + * @file etimer.h + * @brief ETIMER driver header file + * + * 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 "nuc980.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup ETIMER_Driver ETIMER Driver + @{ +*/ + +/** @addtogroup 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 TIMER_TIMEOUT_TRIGGER (0UL) /*!< Timer timeout trigger other modules */ +#define TIMER_CAPTURE_TRIGGER (1UL << 11) /*!< Timer capture trigger other modules */ + +#define TIMER_COUNTER_RISING_EDGE (1UL << 13) /*!< Counter increase on rising edge */ +#define TIMER_COUNTER_FALLING_EDGE (0UL) /*!< Counter increase on falling edge */ + +/*@}*/ /* end of group ETIMER_EXPORTED_CONSTANTS */ + +/** @addtogroup 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 ~ 5 + * @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 if((timer) == 3) {\ + outpw(REG_ETMR3_CMPR, u32Value);\ + } else if((timer) == 4) {\ + outpw(REG_ETMR4_CMPR, u32Value);\ + } else {\ + outpw(REG_ETMR5_CMPR, u32Value);\ + }\ + }while(0) + +/** + * @brief This macro is used to set new Timer prescale value + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if((timer) == 3) {\ + outpw(REG_ETMR3_PRECNT, u32Value);\ + } else if((timer) == 4) {\ + outpw(REG_ETMR4_PRECNT, u32Value);\ + } else {\ + outpw(REG_ETMR5_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 if((timer) == 3) {\ + outpw(REG_ETMR3_CTL, (inpw(REG_ETMR3_CTL)&~0x30) | u32OpMode);\ + } else if((timer) == 4) {\ + outpw(REG_ETMR4_CTL, (inpw(REG_ETMR4_CTL)&~0x30) | u32OpMode);\ + } else {\ + outpw(REG_ETMR5_CTL, (inpw(REG_ETMR5_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 ~ 5 + * @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 if (timer == 3) + { + reg = inpw(REG_ETMR3_CTL); + } + else if (timer == 4) + { + reg = inpw(REG_ETMR4_CTL); + } + else + { + reg = inpw(REG_ETMR5_CTL); + } + return (reg & 0x80) ? 1 : 0; +} + +/** + * @brief This function is used to start Timer counting + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) | 1); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) | 1); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) | 1); + } +} + +/** + * @brief This function is used to stop Timer counting + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~1); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) & ~1); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) & ~1); + } +} + +/** + * @brief This function is used to enable the Timer wake-up function + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) | 4); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) | 4); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) | 4); + } +} + +/** + * @brief This function is used to disable the Timer wake-up function + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~4); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) & ~4); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) & ~4); + } +} + + +/** + * @brief This function is used to enable the capture pin detection de-bounce function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) | 0x400000); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) | 0x400000); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) | 0x400000); + } +} + +/** + * @brief This function is used to disable the capture pin detection de-bounce function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~0x400000); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) & ~0x400000); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) & ~0x400000); + } +} + + +/** + * @brief This function is used to enable the Timer time-out interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) | 1); + } + else if (timer == 4) + { + outpw(REG_ETMR4_IER, inpw(REG_ETMR4_IER) | 1); + } + else + { + outpw(REG_ETMR5_IER, inpw(REG_ETMR5_IER) | 1); + } +} + +/** + * @brief This function is used to disable the Timer time-out interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) & ~1); + } + else if (timer == 4) + { + outpw(REG_ETMR4_IER, inpw(REG_ETMR4_IER) & ~1); + } + else + { + outpw(REG_ETMR5_IER, inpw(REG_ETMR5_IER) & ~1); + } +} + +/** + * @brief This function is used to enable the Timer capture trigger interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) | 2); + } + else if (timer == 4) + { + outpw(REG_ETMR4_IER, inpw(REG_ETMR4_IER) | 2); + } + else + { + outpw(REG_ETMR5_IER, inpw(REG_ETMR5_IER) | 2); + } +} + +/** + * @brief This function is used to disable the Timer capture trigger interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) & ~2); + } + else if (timer == 4) + { + outpw(REG_ETMR4_IER, inpw(REG_ETMR4_IER) & ~2); + } + else + { + outpw(REG_ETMR5_IER, inpw(REG_ETMR5_IER) & ~2); + } +} + +/** + * @brief This function indicates Timer time-out interrupt occurred or not. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + reg = inpw(REG_ETMR3_ISR); + } + else if (timer == 4) + { + reg = inpw(REG_ETMR4_ISR); + } + else + { + reg = inpw(REG_ETMR5_ISR); + } + return reg & 1; +} + +/** + * @brief This function clears the Timer time-out interrupt flag. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_ISR, 1); + } + else if (timer == 4) + { + outpw(REG_ETMR4_ISR, 1); + } + else + { + outpw(REG_ETMR5_ISR, 1); + } +} + +/** + * @brief This function indicates Timer capture interrupt occurred or not. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + reg = inpw(REG_ETMR3_ISR); + } + else if (timer == 4) + { + reg = inpw(REG_ETMR4_ISR); + } + else + { + reg = inpw(REG_ETMR5_ISR); + } + return (reg & 2) >> 1; +} + +/** + * @brief This function clears the Timer capture interrupt flag. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_ISR, 2); + } + else if (timer == 4) + { + outpw(REG_ETMR4_ISR, 2); + } + else + { + outpw(REG_ETMR5_ISR, 2); + } +} + +/** + * @brief This function indicates Timer has waked up system or not. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + reg = inpw(REG_ETMR3_ISR); + } + else if (timer == 4) + { + reg = inpw(REG_ETMR4_ISR); + } + else + { + reg = inpw(REG_ETMR5_ISR); + } + return (reg & 0x10) >> 4; +} + +/** + * @brief This function clears the Timer wakeup interrupt flag. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_ISR, 0x10); + } + else if (timer == 4) + { + outpw(REG_ETMR4_ISR, 0x10); + } + else + { + outpw(REG_ETMR5_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 if (timer == 3) + { + return inpw(REG_ETMR3_CMPR); + } + else if (timer == 4) + { + return inpw(REG_ETMR4_CMPR); + } + else + { + return inpw(REG_ETMR5_CMPR); + } +} + +/** + * @brief This function gets the Timer capture data. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + return inpw(REG_ETMR3_TCAP); + } + else if (timer == 4) + { + return inpw(REG_ETMR4_TCAP); + } + else + { + return inpw(REG_ETMR5_TCAP); + } +} + +/** + * @brief This function reports the current timer counter value. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + return inpw(REG_ETMR3_DR); + } + else if (timer == 4) + { + return inpw(REG_ETMR4_DR); + } + else + { + return inpw(REG_ETMR5_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 if (timer == 3) + { + return outpw(REG_ETMR3_DR, 0); + } + else if (timer == 4) + { + return outpw(REG_ETMR4_DR, 0); + } + else + { + return outpw(REG_ETMR5_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); +void ETIMER_EnableEventCounter(UINT timer, uint32_t u32Edge); +void ETIMER_DisableEventCounter(UINT timer); +UINT ETIMER_GetModuleClock(UINT timer); + +/*@}*/ /* end of group ETIMER_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group ETIMER_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_ETIMER_H__ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_gpio.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_gpio.h new file mode 100644 index 0000000000..2721cc5d39 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_gpio.h @@ -0,0 +1,835 @@ +/**************************************************************************//** + * @file GPIO.h + * @brief 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 + #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 */ + + +#ifdef __cplusplus +extern "C" +{ +#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/0x180/0x1C0 Port A-H I/O Mode Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2n+1:2n]|MODEn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::DINOFF + * Offset: 0x04/0x44/0x84/0xC4/0x104/0x144/0x184/0x1C4 Port A-H Digital Input Path Disable Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n+16] |DINOFFn |Port A-H Pin[n] Digital Input Path Disable Control + * | | |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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::DOUT + * Offset: 0x08/0x48/0x88/0xC8/0x108/0x148/0x188/0x1C8 Port A-H Data Output Value + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |DOUTn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::DATMSK + * Offset: 0x0C/0x4C/0x8C/0xCC/0x10C/0x14C/0x18C/0x1CC Port A-H Data Output Write Mask + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |DATMSKn |Port A-H 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[n]) bit. + * | | |Note2: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::PIN + * Offset: 0x10/0x50/0x90/0xD0/0x110/0x150/0x190/0x1D0 Port A-H Pin Value + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |PINn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::DBEN + * Offset: 0x14/0x54/0x94/0xD4/0x114/0x154/0x194/0x1D4 Port A-H De-Bounce Enable Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |DBENn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::INTTYPE + * Offset: 0x18/0x58/0x98/0xD8/0x118/0x158/0x198/0x1D8 Port A-H Interrupt Trigger Type Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |TYPEn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::INTEN + * Offset: 0x1C/0x5C/0x9C/0xDC/0x11C/0x15C/0x19C/0x1DC Port A-H Interrupt Enable Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |FLIENn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * |[n+16] |RHIENn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::INTSRC + * Offset: 0x20/0x60/0xA0/0xE0/0x120/0x160/0x1A0/0x1E0 Port A-H Interrupt Source Flag + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |INTSRCn |Port A-H 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: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::SMTEN + * Offset: 0x24/0x64/0xA4/0xE4/0x124/0x164/0x1A4/0x1E4 Port A-H Input Schmitt Trigger Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |SMTENn |Port A-H Pin[n] Input Schmitt Trigger Enable Bit + * | | |0 = Px.n input Schmitt trigger function Disabled. + * | | |1 = Px.n input Schmitt trigger function Enabled. + * | | |Note: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::SLEWCTL + * Offset: 0x28/0x68/0xA8/0xE8/0x128/0x168/0x1A8/0x1E8 Port A-H High Slew Rate Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2n+1:2n]|HSRENn |Port A-H Pin[n] High Slew Rate Control + * | | |00 = Px.n output with normal slew rate mode (maximum 40 MHz at 2.7V). + * | | |01 = Px.n output with high slew rate mode (maximum 80 MHz at 2.7V). + * | | |10 = Px.n output with fast slew rate mode (maximum 100 MHz at 2.7V. + * | | |11 = Reserved. + * | | |Note: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + * @var GPIO_T::PUSEL + * Offset: 0x30/0x70/0xB0/0xF0/0x130/0x170/0x1B0/0x1F0 Port A-H Pull-up and Pull-down Selection Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2n+1:2n]|PUSELn |Port A-H Pin[n] Pull-up and Pull-down Enable Register + * | | |Determine each I/O Pull-up/pull-down of Px.n pins. + * | | |00 = Px.n pull-up and pull-up disable. + * | | |01 = Px.n pull-up enable. + * | | |10 = Px.n pull-down enable. + * | | |11 = Px.n pull-up and pull-up disable. + * | | |Note1: + * | | |Basically, the pull-up control and pull-down control has following behavior limitation + * | | |The independent pull-up control register only valid when MODEn set as tri-state and open-drain mode + * | | |The independent pull-down control register only valid when MODEn set as tri-state mode + * | | |When both pull-up pull-down is set as 1 at tri-state mode, keep I/O in tri-state mode + * | | |Note2: + * | | |Max. n=15 for port A/B/E/G. + * | | |Max. n=14 for port C/D. + * | | |Max. n=11 for port F/H. + */ + + __IO uint32_t MODE; /* Offset: 0x00/0x40/0x80/0xC0/0x100/0x140/0x180/0x1C0 Port A-H I/O Mode Control */ + __IO uint32_t DINOFF; /* Offset: 0x04/0x44/0x84/0xC4/0x104/0x144/0x184/0x1C4 Port A-H Digital Input Path Disable Control */ + __IO uint32_t DOUT; /* Offset: 0x08/0x48/0x88/0xC8/0x108/0x148/0x188/0x1C8 Port A-H Data Output Value */ + __IO uint32_t DATMSK; /* Offset: 0x0C/0x4C/0x8C/0xCC/0x10C/0x14C/0x18C/0x1CC Port A-H Data Output Write Mask */ + __I uint32_t PIN; /* Offset: 0x10/0x50/0x90/0xD0/0x110/0x150/0x190/0x1D0 Port A-H Pin Value */ + __IO uint32_t DBEN; /* Offset: 0x14/0x54/0x94/0xD4/0x114/0x154/0x194/0x1D4 Port A-H De-Bounce Enable Control Register */ + __IO uint32_t INTTYPE; /* Offset: 0x18/0x58/0x98/0xD8/0x118/0x158/0x198/0x1D8 Port A-H Interrupt Trigger Type Control */ + __IO uint32_t INTEN; /* Offset: 0x1C/0x5C/0x9C/0xDC/0x11C/0x15C/0x19C/0x1DC Port A-H Interrupt Enable Control Register */ + __IO uint32_t INTSRC; /* Offset: 0x20/0x60/0xA0/0xE0/0x120/0x160/0x1A0/0x1E0 Port A-H Interrupt Source Flag */ + __IO uint32_t SMTEN; /* Offset: 0x24/0x64/0xA4/0xE4/0x124/0x164/0x1A4/0x1E4 Port A-H Input Schmitt Trigger Enable Register */ + __IO uint32_t SLEWCTL; /* Offset: 0x28/0x68/0xA8/0xE8/0x128/0x168/0x1A8/0x1E8 Port A-H High Slew Rate Control Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE0[1]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t PUSEL; /* Offset: 0x30/0x70/0xB0/0xF0/0x130/0x170/0x1B0/0x1F0 Port A-H Pull-up and Pull-down Enable Register */ + +} GPIO_T; + +typedef struct +{ + + /** + * @var GPIO_DBCTL_T::DBCTL + * Offset: 0x440 Interrupt De-bounce Control Register + * --------------------------------------------------------------------------------------------------- + * |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 10 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; /* Offset: 0x440 Interrupt De-bounce Control Register */ + +} GPIO_DBCTL_T; + +/** + @addtogroup GPIO_CONST GPIO Bit Field Definition + Constant Definitions for GPIO Controller +@{ */ + +#define GPIO_DBCTL_DBCLKSEL_Pos (0) /*!< GPIO_T::DBCTL: DBCLKSEL Position */ +#define GPIO_DBCTL_DBCLKSEL_Msk (0xFul << GPIO_DBCTL_DBCLKSEL_Pos) /*!< GPIO_T::DBCTL: DBCLKSEL Mask */ + +#define GPIO_DBCTL_DBCLKSRC_Pos (4) /*!< GPIO_T::DBCTL: DBCLKSRC Position */ +#define GPIO_DBCTL_DBCLKSRC_Msk (1ul << GPIO_DBCTL_DBCLKSRC_Pos) /*!< GPIO_T::DBCTL: DBCLKSRC Mask */ + +#define GPIO_DBCTL_ICLKON_Pos (5) /*!< GPIO_T::DBCTL: ICLKON Position */ +#define GPIO_DBCTL_ICLKON_Msk (1ul << GPIO_DBCTL_ICLKON_Pos) /*!< GPIO_T::DBCTL: ICLKON Mask */ + +/**@}*/ /* GPIO_CONST */ +/**@}*/ /* end of GPIO register group */ +/**@}*/ /* end of REGISTER group */ + +/** @addtogroup PERIPHERAL_DECLARATION Peripheral Pointer + The Declaration of Peripherals + @{ + */ + +#define GPIO_DBCTL_BASE (0xB0004440ul) +#define PA ((GPIO_T *) PA_BA) +#define PB ((GPIO_T *) PB_BA) +#define PC ((GPIO_T *) PC_BA) +#define PD ((GPIO_T *) PD_BA) +#define PE ((GPIO_T *) PE_BA) +#define PF ((GPIO_T *) PF_BA) +#define PG ((GPIO_T *) PG_BA) +#define GPIOA ((GPIO_T *) PA_BA) +#define GPIOB ((GPIO_T *) PB_BA) +#define GPIOC ((GPIO_T *) PC_BA) +#define GPIOD ((GPIO_T *) PD_BA) +#define GPIOE ((GPIO_T *) PE_BA) +#define GPIOF ((GPIO_T *) PF_BA) +#define GPIOG ((GPIO_T *) PG_BA) +#define GPIO ((GPIO_DBCTL_T *) GPIO_DBCTL_BASE) +#define GPIO_PIN_DATA_BASE (0xB0004800ul) +/*@}*/ /* end of group ERIPHERAL_DECLARATION */ + + + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup GPIO_Driver GPIO Driver + @{ +*/ + +/** @addtogroup GPIO_EXPORTED_CONSTANTS GPIO Exported Constants + @{ +*/ + + +#define GPIO_PIN_MAX 16UL /*!< Specify Maximum Pins of Each GPIO Port \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 */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO Interrupt Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#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-Level \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 Edge Level Mode \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO Slew Rate Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_SLEWCTL_NORMAL 0x0UL /*!< GPIO slew setting for nornal Mode \hideinitializer */ +#define GPIO_SLEWCTL_HIGH 0x1UL /*!< GPIO slew setting for high Mode \hideinitializer */ +#define GPIO_SLEWCTL_FAST 0x2UL /*!< GPIO slew setting for fast Mode \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO Pull-up And Pull-down Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_PUSEL_DISABLE 0x0UL /*!< GPIO PUSEL setting for Disable Mode \hideinitializer */ +#define GPIO_PUSEL_PULL_UP 0x1UL /*!< GPIO PUSEL setting for Pull-up Mode \hideinitializer */ +#define GPIO_PUSEL_PULL_DOWN 0x2UL /*!< GPIO PUSEL setting for Pull-down Mode \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO External interrupt Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_MFP_PA0MFP_EINT0 outpw(REG_SYS_GPA_MFPL, ((inpw(REG_SYS_GPA_MFPL) & 0xFFFFFFF0) | 0x00000005)) /*!< PA0 MFP setting for EINT0 \hideinitializer */ +#define GPIO_MFP_PA13MFP_EINT0 outpw(REG_SYS_GPA_MFPH, ((inpw(REG_SYS_GPA_MFPH) & 0xFF0FFFFF) | 0x00D00000)) /*!< PA13 MFP setting for EINT0 \hideinitializer */ +#define GPIO_MFP_PA1MFP_EINT1 outpw(REG_SYS_GPA_MFPL, ((inpw(REG_SYS_GPA_MFPL) & 0xFFFFFF0F) | 0x000000D0)) /*!< PA1 MFP setting for EINT1 \hideinitializer */ +#define GPIO_MFP_PA14MFP_EINT1 outpw(REG_SYS_GPA_MFPH, ((inpw(REG_SYS_GPA_MFPH) & 0xF0FFFFFF) | 0x08000000)) /*!< PA14 MFP setting for EINT1 \hideinitializer */ +#define GPIO_MFP_PD0MFP_EINT2 outpw(REG_SYS_GPD_MFPL, ((inpw(REG_SYS_GPD_MFPL) & 0xFFFFFFF0) | 0x00000004)) /*!< PD0 MFP setting for EINT2 \hideinitializer */ +#define GPIO_MFP_PE10MFP_EINT2 outpw(REG_SYS_GPE_MFPH, ((inpw(REG_SYS_GPE_MFPH) & 0xFFFFF0FF) | 0x00000500)) /*!< PE10 MFP setting for EINT2 \hideinitializer */ +#define GPIO_MFP_PB3MFP_EINT2 outpw(REG_SYS_GPB_MFPL, ((inpw(REG_SYS_GPB_MFPL) & 0xFFFF0FFF) | 0x00003000)) /*!< PB3 MFP setting for EINT2 \hideinitializer */ +#define GPIO_MFP_PB13MFP_EINT2 outpw(REG_SYS_GPB_MFPH, ((inpw(REG_SYS_GPB_MFPH) & 0xFF0FFFFF) | 0x00200000)) /*!< PB13 MFP setting for EINT2 \hideinitializer */ +#define GPIO_MFP_PD1MFP_EINT3 outpw(REG_SYS_GPD_MFPL, ((inpw(REG_SYS_GPD_MFPL) & 0xFFFFFF0F) | 0x00000040)) /*!< PD1 MFP setting for EINT3 \hideinitializer */ +#define GPIO_MFP_PE12MFP_EINT3 outpw(REG_SYS_GPE_MFPH, ((inpw(REG_SYS_GPE_MFPH) & 0xFFF0FFFF) | 0x00050000)) /*!< PE12 MFP setting for EINT3 \hideinitializer */ +#define GPIO_MFP_PG15MFP_EINT3 outpw(REG_SYS_GPG_MFPH, ((inpw(REG_SYS_GPG_MFPH) & 0x0FFFFFFF) | 0x40000000)) /*!< PG15 MFP setting for EINT3 \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO_DBCTL Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_DBCTL_ICLK_ON 0x00000020UL /*!< GPIO_DBCTL setting for all IO pins edge detection circuit is always active after reset \hideinitializer */ +#define GPIO_DBCTL_ICLK_OFF 0x00000000UL /*!< GPIO_DBCTL setting for edge detection circuit is active only if IO pin corresponding GPIOx_IEN bit is set to 1 \hideinitializer */ + +#define GPIO_DBCTL_DBCLKSRC_LIRC 0x00000010UL /*!< GPIO_DBCTL setting for de-bounce counter clock source is the internal 10 kHz \hideinitializer */ +#define GPIO_DBCTL_DBCLKSRC_HCLK 0x00000000UL /*!< GPIO_DBCTL setting for de-bounce counter clock source is the HCLK \hideinitializer */ + +#define GPIO_DBCTL_DBCLKSEL_1 0x00000000UL /*!< GPIO_DBCTL setting for sampling cycle = 1 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_2 0x00000001UL /*!< GPIO_DBCTL setting for sampling cycle = 2 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_4 0x00000002UL /*!< GPIO_DBCTL setting for sampling cycle = 4 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_8 0x00000003UL /*!< GPIO_DBCTL setting for sampling cycle = 8 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_16 0x00000004UL /*!< GPIO_DBCTL setting for sampling cycle = 16 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_32 0x00000005UL /*!< GPIO_DBCTL setting for sampling cycle = 32 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_64 0x00000006UL /*!< GPIO_DBCTL setting for sampling cycle = 64 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_128 0x00000007UL /*!< GPIO_DBCTL setting for sampling cycle = 128 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_256 0x00000008UL /*!< GPIO_DBCTL setting for sampling cycle = 256 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_512 0x00000009UL /*!< GPIO_DBCTL setting for sampling cycle = 512 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_1024 0x0000000AUL /*!< GPIO_DBCTL setting for sampling cycle = 1024 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_2048 0x0000000BUL /*!< GPIO_DBCTL setting for sampling cycle = 2048 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_4096 0x0000000CUL /*!< GPIO_DBCTL setting for sampling cycle = 4096 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_8192 0x0000000DUL /*!< GPIO_DBCTL setting for sampling cycle = 8192 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_16384 0x0000000EUL /*!< GPIO_DBCTL setting for sampling cycle = 16384 clocks \hideinitializer */ +#define GPIO_DBCTL_DBCLKSEL_32768 0x0000000FUL /*!< GPIO_DBCTL setting for sampling cycle = 32768 clocks \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)))) /*!< 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 PC15 GPIO_PIN_DATA(2, 15) /*!< Specify PC.15 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 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 PG0 GPIO_PIN_DATA(6, 0 ) /*!< Specify PG.0 Pin Data Input/Output \hideinitializer */ +#define PG1 GPIO_PIN_DATA(6, 1 ) /*!< Specify PG.1 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 PG5 GPIO_PIN_DATA(6, 5 ) /*!< Specify PG.5 Pin Data Input/Output \hideinitializer */ +#define PG6 GPIO_PIN_DATA(6, 6 ) /*!< Specify PG.6 Pin Data Input/Output \hideinitializer */ +#define PG7 GPIO_PIN_DATA(6, 7 ) /*!< Specify PG.7 Pin Data Input/Output \hideinitializer */ +#define PG8 GPIO_PIN_DATA(6, 8 ) /*!< Specify PG.8 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 PH0 GPIO_PIN_DATA(7, 0 ) /*!< Specify PH.0 Pin Data Input/Output \hideinitializer */ +#define PH1 GPIO_PIN_DATA(7, 1 ) /*!< Specify PH.1 Pin Data Input/Output \hideinitializer */ +#define PH2 GPIO_PIN_DATA(7, 2 ) /*!< Specify PH.2 Pin Data Input/Output \hideinitializer */ +#define PH3 GPIO_PIN_DATA(7, 3 ) /*!< Specify PH.3 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 */ + + +/*@}*/ /* end of group GPIO_EXPORTED_CONSTANTS */ + + +/** @addtogroup GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions + @{ +*/ + +/** + * @brief Clear GPIO Pin Interrupt Flag + * + * @param[in] port GPIO port. It could be 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @return None + * + * @details Clear the interrupt status of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_CLR_INT_FLAG(port, u32PinMask) ((port)->INTSRC = (u32PinMask)) + +/** + * @brief Disable Pin De-bounce Function + * + * @param[in] port GPIO port. It could be 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * @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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * + * @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 GPIO_DBCTL_DBCLKSRC_HCLK or 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-debounce counter clock source is internal 10 KHz and sampling cycle selection is 4. \n + * Then the target de-bounce sampling cycle time is (4)*(1/(10*1000)) s = 4*0.0001 s = 400 us, + * and system will sampling interrupt input once per 00 us. + * \hideinitializer + */ +#define GPIO_SET_DEBOUNCE_TIME(u32ClkSrc, u32ClkSel) (GPIO->DBCTL = (GPIO_DBCTL_ICLKON_Msk | (u32ClkSrc) | (u32ClkSel))) + +/** + * @brief Get GPIO Port IN Data + * +* @param[in] port GPIO port. It could be 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 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 It could be PA, PB, PC, PD, PE, PF, PG or PH. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port. + * It could be 0 ~ 13 for PE GPIO port. + * It could be 0 ~ 11 for PG GPIO port. + * @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n + * GPIO_INT_RISING, GPIO_INT_FALLING, GPIO_INT_BOTH_EDGE, GPIO_INT_HIGH, 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 It could be PA, PB, PC, PD, PE, PF, PG or PH. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port. + * It could be 0 ~ 13 for PE GPIO port. + * It could be 0 ~ 11 for PG GPIO port. + * + * @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); +void GPIO_SetSlewCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode); +void GPIO_SetPullCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode); + + +/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group GPIO_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __GPIO_H__ */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2c.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2c.h new file mode 100644 index 0000000000..800d409f71 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2c.h @@ -0,0 +1,541 @@ +/****************************************************************************//** + * @file i2c.h + * @version V1.00 + * @brief NUC980 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__ + +#include +#include +#include +#include "nuc980.h" + + +/** @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 */ + +/*@}*/ /* end of group I2C_EXPORTED_CONSTANTS */ + +typedef struct +{ + volatile uint32_t CTL0; /*!< [0x0000] I2C Control Register 0 */ + volatile uint32_t ADDR0; /*!< [0x0004] I2C Slave Address Register0 */ + volatile uint32_t DAT; /*!< [0x0008] I2C Data Register */ + volatile uint32_t STATUS0; /*!< [0x000c] I2C Status Register 0 */ + volatile uint32_t CLKDIV; /*!< [0x0010] I2C Clock Divided Register */ + volatile uint32_t TOCTL; /*!< [0x0014] I2C Time-out Control Register */ + volatile uint32_t ADDR1; /*!< [0x0018] I2C Slave Address Register1 */ + volatile uint32_t ADDR2; /*!< [0x001c] I2C Slave Address Register2 */ + volatile uint32_t ADDR3; /*!< [0x0020] I2C Slave Address Register3 */ + volatile uint32_t ADDRMSK0; /*!< [0x0024] I2C Slave Address Mask Register0 */ + volatile uint32_t ADDRMSK1; /*!< [0x0028] I2C Slave Address Mask Register1 */ + volatile uint32_t ADDRMSK2; /*!< [0x002c] I2C Slave Address Mask Register2 */ + volatile uint32_t ADDRMSK3; /*!< [0x0030] I2C Slave Address Mask Register3 */ + volatile uint32_t RESERVE0[2]; + volatile uint32_t WKCTL; /*!< [0x003c] I2C Wake-up Control Register */ + volatile uint32_t WKSTS; /*!< [0x0040] I2C Wake-up Status Register */ + volatile uint32_t CTL1; /*!< [0x0044] I2C Control Register 1 */ + volatile uint32_t STATUS1; /*!< [0x0048] I2C Status Register 1 */ + volatile uint32_t TMCTL; /*!< [0x004c] I2C Timing Configure Control Register */ + volatile uint32_t BUSCTL; /*!< [0x0050] I2C Bus Management Control Register */ + volatile uint32_t BUSTCTL; /*!< [0x0054] I2C Bus Management Timer Control Register */ + volatile uint32_t BUSSTS; /*!< [0x0058] I2C Bus Management Status Register */ + volatile uint32_t PKTSIZE; /*!< [0x005c] I2C Packet Error Checking Byte Number Register */ + volatile uint32_t PKTCRC; /*!< [0x0060] I2C Packet Error Checking Byte Value Register */ + volatile uint32_t BUSTOUT; /*!< [0x0064] I2C Bus Management Timer Register */ + volatile uint32_t CLKTOUT; /*!< [0x0068] I2C Bus Management Clock Low Timer Register */ + +} I2C_T; + +#define I2C_CTL0_AA_Pos (2) /*!< I2C_T::CTL: AA Position */ +#define I2C_CTL0_AA_Msk (0x1ul << I2C_CTL0_AA_Pos) /*!< I2C_T::CTL: AA Mask */ + +#define I2C_CTL0_SI_Pos (3) /*!< I2C_T::CTL: SI Position */ +#define I2C_CTL0_SI_Msk (0x1ul << I2C_CTL0_SI_Pos) /*!< I2C_T::CTL: SI Mask */ + +#define I2C_CTL0_STO_Pos (4) /*!< I2C_T::CTL: STO Position */ +#define I2C_CTL0_STO_Msk (0x1ul << I2C_CTL0_STO_Pos) /*!< I2C_T::CTL: STO Mask */ + +#define I2C_CTL0_STA_Pos (5) /*!< I2C_T::CTL: STA Position */ +#define I2C_CTL0_STA_Msk (0x1ul << I2C_CTL0_STA_Pos) /*!< I2C_T::CTL: STA Mask */ + +#define I2C_CTL0_I2CEN_Pos (6) /*!< I2C_T::CTL: I2CEN Position */ +#define I2C_CTL0_I2CEN_Msk (0x1ul << I2C_CTL0_I2CEN_Pos) /*!< I2C_T::CTL: I2CEN Mask */ + +#define I2C_CTL0_INTEN_Pos (7) /*!< I2C_T::CTL: INTEN Position */ +#define I2C_CTL0_INTEN_Msk (0x1ul << I2C_CTL0_INTEN_Pos) /*!< I2C_T::CTL: 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 (0x3fful << 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::STATUS: STATUS Position */ +#define I2C_STATUS0_STATUS_Msk (0xfful << I2C_STATUS_STATUS0_Pos) /*!< I2C_T::STATUS: 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 (0x3fful << 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 (0x3fful << 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 (0x3fful << 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 (0x3fful << 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 (0x3fful << 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 (0x3fful << 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 (0x3fful << 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_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_CTL1_ADDR10EN_Pos (9) /*!< I2C_T::CTL1: ADDR10EN Position */ +#define I2C_CTL1_ADDR10EN_Msk (0x1ul << I2C_CTL1_ADDR10EN_Pos) /*!< I2C_T::CTL1: ADDR10EN Mask */ + +#define I2C_STATUS1_ADMAT0_Pos (0) /*!< I2C_T::STATUS1: ADMAT0 Position */ +#define I2C_STATUS1_ADMAT0_Msk (0x1ul << I2C_STATUS1_ADMAT0_Pos) /*!< I2C_T::STATUS1: ADMAT0 Mask */ + +#define I2C_STATUS1_ADMAT1_Pos (1) /*!< I2C_T::STATUS1: ADMAT1 Position */ +#define I2C_STATUS1_ADMAT1_Msk (0x1ul << I2C_STATUS1_ADMAT1_Pos) /*!< I2C_T::STATUS1: ADMAT1 Mask */ + +#define I2C_STATUS1_ADMAT2_Pos (2) /*!< I2C_T::STATUS1: ADMAT2 Position */ +#define I2C_STATUS1_ADMAT2_Msk (0x1ul << I2C_STATUS1_ADMAT2_Pos) /*!< I2C_T::STATUS1: ADMAT2 Mask */ + +#define I2C_STATUS1_ADMAT3_Pos (3) /*!< I2C_T::STATUS1: ADMAT3 Position */ +#define I2C_STATUS1_ADMAT3_Msk (0x1ul << I2C_STATUS1_ADMAT3_Pos) /*!< I2C_T::STATUS1: ADMAT3 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 */ + + +#define I2C0 ((I2C_T *) I2C0_BA) +#define I2C1 ((I2C_T *) I2C1_BA) +#define I2C2 ((I2C_T *) I2C2_BA) +#define I2C3 ((I2C_T *) I2C3_BA) + + + + + + + + + + + + + +/** @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 I2CDAT 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 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 */ +void I2C_STOP(I2C_T *i2c); + +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); + +/*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group I2C_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + +#endif + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2s.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2s.h new file mode 100644 index 0000000000..2a9df8dce4 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_i2s.h @@ -0,0 +1,132 @@ +/**************************************************************************//** +* @file i2s.h +* @version V1.00 +* $Revision: 2 $ +* $Date: 18/08/05 2:12p $ +* @brief 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 Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup I2S_Driver I2S Driver + @{ +*/ + +/** @addtogroup 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 ARM9_I2S_EXPORTED_CONSTANTS */ + +/** @addtogroup ARM9_I2S_EXPORTED_FUNCTIONS I2S Exported Functions + @{ +*/ + +int32_t i2sOpen(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 I2S_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group I2S_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_I2S_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pdma.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pdma.h new file mode 100644 index 0000000000..2253359ae8 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pdma.h @@ -0,0 +1,1249 @@ +/**************************************************************************//** + * @file pdma.h + * @brief 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 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[n] 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 transfer task in the Descriptor Table, user must check if the descriptor table is complete. + * |[2] |TXTYPE |Transfer Type + * | | |0 = Burst transfer type. + * | | |1 = Single transfer type. + * |[6:4] |BURSIZE |Burst Size + * | | |This field is used for peripheral to determine the burst size or used for determine the re-arbitration 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 when PDMA controller finishes transfer task, it will not generates transfer done interrupt. + * | | |0 = Table interrupt Enabled. + * | | |1 = Table interrupt Disabled. + * |[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. + * |[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. + * |[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 + * |[14] |TXACK |Transfer Acknowledge Selection + * | | |0 = transfer ack when transfer done. + * | | |1 = transfer ack when PDMA get transfer data. + * |[15] |STRIDEEN |Stride Mode Enable Bit + * | | |0 = Stride transfer mode Disabled. + * | | |1 = Stride transfer mode Enabled. + * |[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 Register + * | | |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 Register + * | | |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] |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. + * |[31:16] |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. + */ + __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] First Scatter-Gather Descriptor Table Offset Address of PDMA Channel n */ +} DSCT_T; + + +typedef struct +{ + /** + * @var STRIDE_T::STCR + * Offset: 0x500 Stride Transfer Count Register of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |STC |PDMA Stride Transfer Count + * | | |The 16-bit register defines the stride transfer count of each row. + * @var STRIDE_T::ASOCR + * Offset: 0x504 Address Stride Offset Register of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |SASOL |VDMA Source Address Stride Offset Length + * | | |The 16-bit register defines the source address stride transfer offset count of each row. + * |[31:16] |DASOL |VDMA Destination Address Stride Offset Length + * | | |The 16-bit register defines the destination address stride transfer offset count of each row. + */ + __IO uint32_t STCR; /*!< [0x0500] Stride Transfer Count Register of PDMA Channel 0 */ + __IO uint32_t ASOCR; /*!< [0x0504] Address Stride Offset Register of PDMA Channel 0 */ +} STRIDE_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 Register (Read Only) + * | | |This field indicates a 32-bit current external description address of PDMA controller. + * | | |Note: This field is read only and only used for Scatter-Gather mode to indicate the current external description address. + * @var PDMA_T::CHCTL + * Offset: 0x400 PDMA Channel Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CHENn |PDMA Channel Enable Bit + * | | |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: Set corresponding bit of PDMA_PAUSE or PDMA_CHRST register will also clear this bit. + * @var PDMA_T::PAUSE + * Offset: 0x404 PDMA Transfer Stop Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |PAUSEn |PDMA Transfer Pause Control Register (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..7) and clear request active flag + * | | |If re-enable the paused channel 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 + * | :----: | :----: | :---- | + * |[15:0] |SWREQn |PDMA Software Request Register (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 + * | :----: | :----: | :---- | + * |[15: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 current transfer. + * @var PDMA_T::PRISET + * Offset: 0x410 PDMA Fixed Priority Setting Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FPRISETn |PDMA Fixed Priority Setting Register + * | | |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 + * | :----: | :----: | :---- | + * |[15:0] |FPRICLRn |PDMA Fixed Priority Clear Register (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 + * | :----: | :----: | :---- | + * |[15:0] |INTENn |PDMA Interrupt Enable Register + * | | |This field is used for enabling 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 + * | :----: | :----: | :---- | + * |[15: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 + * | :----: | :----: | :---- | + * |[15:0] |TDIFn |Transfer Done Flag Register + * | | |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 + * | :----: | :----: | :---- | + * |[15:0] |ALIGNn |Transfer Alignment Flag Register + * | | |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 + * | :----: | :----: | :---- | + * |[15:0] |TXACTFn |Transfer on Active Flag Register (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/28. + * | | |001 = PDMA channel 0 time-out clock source is HCLK/29. + * | | |010 = PDMA channel 0 time-out clock source is HCLK/210. + * | | |011 = PDMA channel 0 time-out clock source is HCLK/211. + * | | |100 = PDMA channel 0 time-out clock source is HCLK/212. + * | | |101 = PDMA channel 0 time-out clock source is HCLK/213. + * | | |110 = PDMA channel 0 time-out clock source is HCLK/214. + * | | |111 = PDMA channel 0 time-out clock source is HCLK/215. + * |[6:4] |TOUTPSC1 |PDMA Channel 1 Time-out Clock Source Prescaler Bits + * | | |000 = PDMA channel 1 time-out clock source is HCLK/28. + * | | |001 = PDMA channel 1 time-out clock source is HCLK/29. + * | | |010 = PDMA channel 1 time-out clock source is HCLK/210. + * | | |011 = PDMA channel 1 time-out clock source is HCLK/211. + * | | |100 = PDMA channel 1 time-out clock source is HCLK/212. + * | | |101 = PDMA channel 1 time-out clock source is HCLK/213. + * | | |110 = PDMA channel 1 time-out clock source is HCLK/214. + * | | |111 = PDMA channel 1 time-out clock source is HCLK/215. + * @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 Disable. + * | | |1 = PDMA Channel n time-out function Enable. + * @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 Disable. + * | | |1 = PDMA Channel n time-out interrupt Enable. + * @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 Register + * | | |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 10 kHz clock. + * |[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 10 kHz clock. + * @var PDMA_T::CHRST + * Offset: 0x460 PDMA Channel Reset Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CHnRST |Channel N Reset + * | | |0 = corresponding channel n not reset. + * | | |1 = corresponding channel n is reset. + * @var PDMA_T::REQSEL0_3 + * Offset: 0x480 PDMA Request Source Select Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6: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 = Channel connects to USB_TX. + * | | |3 = Channel connects to USB_RX. + * | | |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 UART3_TX. + * | | |11 = Channel connects to UART3_RX. + * | | |12 = Channel connects to UART4_TX. + * | | |13 = Channel connects to UART4_RX. + * | | |14 = Channel connects to UART5_TX. + * | | |15 = Channel connects to UART5_RX. + * | | |16 = Channel connects to USCI0_TX. + * | | |17 = Channel connects to USCI0_RX. + * | | |18 = Channel connects to USCI1_TX. + * | | |19 = Channel connects to USCI1_RX. + * | | |20 = Channel connects to QSPI0_TX. + * | | |21 = Channel connects to QSPI0_RX. + * | | |22 = Channel connects to SPI0_TX. + * | | |23 = Channel connects to SPI0_RX. + * | | |24 = Channel connects to SPI1_TX. + * | | |25 = Channel connects to SPI1_RX. + * | | |26 = Channel connects to SPI2_TX. + * | | |27 = Channel connects to SPI2_RX. + * | | |28 = Channel connects to SPI3_TX. + * | | |29 = Channel connects to SPI3_RX. + * | | |30 = Reserved. + * | | |31 = Reserved. + * | | |32 = Channel connects to EPWM0_P1_RX. + * | | |33 = Channel connects to EPWM0_P2_RX. + * | | |34 = Channel connects to EPWM0_P3_RX. + * | | |35 = Channel connects to EPWM1_P1_RX. + * | | |36 = Channel connects to EPWM1_P2_RX. + * | | |37 = Channel connects to EPWM1_P3_RX. + * | | |38 = Channel connects to I2C0_TX. + * | | |39 = Channel connects to I2C0_RX. + * | | |40 = Channel connects to I2C1_TX. + * | | |41 = Channel connects to I2C1_RX. + * | | |42 = Channel connects to I2C2_TX. + * | | |43 = Channel connects to I2C2_RX. + * | | |44 = Channel connects to I2S0_TX. + * | | |45 = Channel connects to I2S0_RX. + * | | |46 = Channel connects to TMR0. + * | | |47 = Channel connects to TMR1. + * | | |48 = Channel connects to TMR2. + * | | |49 = Channel connects to TMR3. + * | | |50 = Channel connects to ADC_RX. + * | | |51 = Channel connects to DAC0_TX. + * | | |52 = Channel connects to DAC1_TX. + * | | |53 = Channel connects to EPWM0_CH0_TX. + * | | |54 = Channel connects to EPWM0_CH1_TX. + * | | |55 = Channel connects to EPWM0_CH2_TX. + * | | |56 = Channel connects to EPWM0_CH3_TX. + * | | |57 = Channel connects to EPWM0_CH4_TX. + * | | |58 = Channel connects to EPWM0_CH5_TX. + * | | |59 = Channel connects to EPWM1_CH0_TX. + * | | |60 = Channel connects to EPWM1_CH1_TX. + * | | |61 = Channel connects to EPWM1_CH2_TX. + * | | |62 = Channel connects to EPWM1_CH3_TX. + * | | |63 = Channel connects to EPWM1_CH4_TX. + * | | |64 = Channel connects to EPWM1_CH5_TX. + * | | |65 = Channel connects to ETMC_RX. + * | | |Others = Reserved. + * | | |Note 1: A peripheral can't assign to two channels at the same time. + * | | |Note 2: This field is useless when transfer between memory and memory. + * |[14: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. + * |[22: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. + * |[30: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 + * | :----: | :----: | :---- | + * |[6: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. + * |[14: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. + * |[22: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. + * |[30: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_11 + * Offset: 0x488 PDMA Request Source Select Register 2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6: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. + * |[14:8] |REQSRC9 |Channel 9 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 9 + * | | |User can configure the peripheral setting by REQSRC9. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + * |[22:16] |REQSRC10 |Channel 10 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 10 + * | | |User can configure the peripheral setting by REQSRC10. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + * |[30:24] |REQSRC11 |Channel 11 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 11 + * | | |User can configure the peripheral setting by REQSRC11. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + * @var PDMA_T::REQSEL12_15 + * Offset: 0x48C PDMA Request Source Select Register 3 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6:0] |REQSRC12 |Channel 12 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 12 + * | | |User can configure the peripheral setting by REQSRC12. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + * |[14:8] |REQSRC13 |Channel 13 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 13 + * | | |User can configure the peripheral setting by REQSRC13. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + * |[22:16] |REQSRC14 |Channel 14 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 14 + * | | |User can configure the peripheral setting by REQSRC14. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + * |[30:24] |REQSRC15 |Channel 15 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 15 + * | | |User can configure the peripheral setting by REQSRC15. + * | | |Note: The channel configuration is the same as REQSRC0 field + * | | |Please refer to the explanation of REQSRC0. + */ + DSCT_T DSCT[16]; + __I uint32_t CURSCAT[16]; /*!< [0x0100] Current Scatter-Gather Descriptor Table Address of PDMA Channel n */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE1[176]; + /// @endcond //HIDDEN_SYMBOLS + __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 */ + __IO uint32_t TOC2_3; /*!< [0x0444] PDMA Time-out Counter Ch1 and Ch0 Register */ + __IO uint32_t TOC4_5; /*!< [0x0448] PDMA Time-out Counter Ch1 and Ch0 Register */ + __IO uint32_t TOC6_7; /*!< [0x044c] PDMA Time-out Counter Ch1 and Ch0 Register */ + __IO uint32_t TOC8_9; /*!< [0x0450] PDMA Time-out Counter Ch1 and Ch0 Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE2[3]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t CHRST; /*!< [0x0460] PDMA Channel Reset Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE5[3]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t TOUTPSC2; /*!< [0x0470] PPDMA Time-out Prescaler Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE3[3]; + /// @endcond //HIDDEN_SYMBOLS + __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_11; /*!< [0x0488] PDMA Request Source Select Register 2 */ + __IO uint32_t REQSEL12_15; /*!< [0x048c] PDMA Request Source Select Register 3 */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE4[28]; + /// @endcond //HIDDEN_SYMBOLS + STRIDE_T STRIDE[6]; +} PDMA_T; + +/** + @addtogroup PDMA_CONST PDMA Bit Field Definition + Constant Definitions for PDMA Controller +@{ */ + +#define PDMA_DSCT_CTL_OPMODE_Pos (0) /*!< PDMA_T::DSCT_CTL: OPMODE Position */ +#define PDMA_DSCT_CTL_OPMODE_Msk (0x3ul << PDMA_DSCT_CTL_OPMODE_Pos) /*!< PDMA_T::DSCT_CTL: OPMODE Mask */ + +#define PDMA_DSCT_CTL_TXTYPE_Pos (2) /*!< PDMA_T::DSCT_CTL: TXTYPE Position */ +#define PDMA_DSCT_CTL_TXTYPE_Msk (0x1ul << PDMA_DSCT_CTL_TXTYPE_Pos) /*!< PDMA_T::DSCT_CTL: TXTYPE Mask */ + +#define PDMA_DSCT_CTL_BURSIZE_Pos (4) /*!< PDMA_T::DSCT_CTL: BURSIZE Position */ +#define PDMA_DSCT_CTL_BURSIZE_Msk (0x7ul << PDMA_DSCT_CTL_BURSIZE_Pos) /*!< PDMA_T::DSCT_CTL: BURSIZE Mask */ + +#define PDMA_DSCT_CTL_TBINTDIS_Pos (7) /*!< PDMA_T::DSCT_CTL: TBINTDIS Position */ +#define PDMA_DSCT_CTL_TBINTDIS_Msk (0x1ul << PDMA_DSCT_CTL_TBINTDIS_Pos) /*!< PDMA_T::DSCT_CTL: TBINTDIS Mask */ + +#define PDMA_DSCT_CTL_SAINC_Pos (8) /*!< PDMA_T::DSCT_CTL: SAINC Position */ +#define PDMA_DSCT_CTL_SAINC_Msk (0x3ul << PDMA_DSCT_CTL_SAINC_Pos) /*!< PDMA_T::DSCT_CTL: SAINC Mask */ + +#define PDMA_DSCT_CTL_DAINC_Pos (10) /*!< PDMA_T::DSCT_CTL: DAINC Position */ +#define PDMA_DSCT_CTL_DAINC_Msk (0x3ul << PDMA_DSCT_CTL_DAINC_Pos) /*!< PDMA_T::DSCT_CTL: DAINC Mask */ + +#define PDMA_DSCT_CTL_TXWIDTH_Pos (12) /*!< PDMA_T::DSCT_CTL: TXWIDTH Position */ +#define PDMA_DSCT_CTL_TXWIDTH_Msk (0x3ul << PDMA_DSCT_CTL_TXWIDTH_Pos) /*!< PDMA_T::DSCT_CTL: TXWIDTH Mask */ + +#define PDMA_DSCT_CTL_TXACK_Pos (14) /*!< PDMA_T::DSCT_CTL: TXACK Position */ +#define PDMA_DSCT_CTL_TXACK_Msk (0x1ul << PDMA_DSCT_CTL_TXACK_Pos) /*!< PDMA_T::DSCT_CTL: TXACK Mask */ + +#define PDMA_DSCT_CTL_STRIDEEN_Pos (15) /*!< PDMA_T::DSCT_CTL: STRIDEEN Position */ +#define PDMA_DSCT_CTL_STRIDEEN_Msk (0x1ul << PDMA_DSCT_CTL_STRIDEEN_Pos) /*!< PDMA_T::DSCT_CTL: STRIDEEN Mask */ + +#define PDMA_DSCT_CTL_TXCNT_Pos (16) /*!< PDMA_T::DSCT_CTL: TXCNT Position */ +#define PDMA_DSCT_CTL_TXCNT_Msk (0xfffful << PDMA_DSCT_CTL_TXCNT_Pos) /*!< PDMA_T::DSCT_CTL: TXCNT Mask */ + +#define PDMA_DSCT_SA_SA_Pos (0) /*!< PDMA_T::DSCT_SA: SA Position */ +#define PDMA_DSCT_SA_SA_Msk (0xfffffffful << PDMA_DSCT_SA_SA_Pos) /*!< PDMA_T::DSCT_SA: SA Mask */ + +#define PDMA_DSCT_DA_DA_Pos (0) /*!< PDMA_T::DSCT_DA: DA Position */ +#define PDMA_DSCT_DA_DA_Msk (0xfffffffful << PDMA_DSCT_DA_DA_Pos) /*!< PDMA_T::DSCT_DA: DA Mask */ + +#define PDMA_DSCT_NEXT_NEXT_Pos (0) /*!< PDMA_T::DSCT_NEXT: NEXT Position */ +#define PDMA_DSCT_NEXT_NEXT_Msk (0xfffful << PDMA_DSCT_NEXT_NEXT_Pos) /*!< PDMA_T::DSCT_NEXT: NEXT Mask */ + +#define PDMA_DSCT_NEXT_EXENEXT_Pos (16) /*!< PDMA_T::DSCT_FIRST: NEXT Position */ +#define PDMA_DSCT_NEXT_EXENEXT_Msk (0xfffful << PDMA_DSCT_NEXT_EXENEXT_Pos) /*!< PDMA_T::DSCT_FIRST: NEXT 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 (0xfffful << 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 (0xfffful << 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 (0xfffful << 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 (0xfffful << 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 (0xfffful << 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 (0xfffful << 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 (0xfffful << 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_REQTOFn_Msk (0x3FFul << PDMA_INTSTS_REQTOF0_Pos) /*!< PDMA_T::INTSTS: REQTOFX 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_INTSTS_REQTOF2_Pos (10) /*!< PDMA_T::INTSTS: REQTOF2 Position */ +#define PDMA_INTSTS_REQTOF2_Msk (0x1ul << PDMA_INTSTS_REQTOF2_Pos) /*!< PDMA_T::INTSTS: REQTOF2 Mask */ + +#define PDMA_INTSTS_REQTOF3_Pos (11) /*!< PDMA_T::INTSTS: REQTOF3 Position */ +#define PDMA_INTSTS_REQTOF3_Msk (0x1ul << PDMA_INTSTS_REQTOF3_Pos) /*!< PDMA_T::INTSTS: REQTOF3 Mask */ + +#define PDMA_INTSTS_REQTOF4_Pos (12) /*!< PDMA_T::INTSTS: REQTOF4 Position */ +#define PDMA_INTSTS_REQTOF4_Msk (0x1ul << PDMA_INTSTS_REQTOF4_Pos) /*!< PDMA_T::INTSTS: REQTOF4 Mask */ + +#define PDMA_INTSTS_REQTOF5_Pos (13) /*!< PDMA_T::INTSTS: REQTOF5 Position */ +#define PDMA_INTSTS_REQTOF5_Msk (0x1ul << PDMA_INTSTS_REQTOF5_Pos) /*!< PDMA_T::INTSTS: REQTOF5 Mask */ + +#define PDMA_INTSTS_REQTOF6_Pos (14) /*!< PDMA_T::INTSTS: REQTOF6 Position */ +#define PDMA_INTSTS_REQTOF6_Msk (0x1ul << PDMA_INTSTS_REQTOF6_Pos) /*!< PDMA_T::INTSTS: REQTOF6 Mask */ + +#define PDMA_INTSTS_REQTOF7_Pos (15) /*!< PDMA_T::INTSTS: REQTOF7 Position */ +#define PDMA_INTSTS_REQTOF7_Msk (0x1ul << PDMA_INTSTS_REQTOF7_Pos) /*!< PDMA_T::INTSTS: REQTOF7 Mask */ + +#define PDMA_INTSTS_REQTOF8_Pos (16) /*!< PDMA_T::INTSTS: REQTOF8 Position */ +#define PDMA_INTSTS_REQTOF8_Msk (0x1ul << PDMA_INTSTS_REQTOF8_Pos) /*!< PDMA_T::INTSTS: REQTOF8 Mask */ + +#define PDMA_INTSTS_REQTOF9_Pos (17) /*!< PDMA_T::INTSTS: REQTOF9 Position */ +#define PDMA_INTSTS_REQTOF9_Msk (0x1ul << PDMA_INTSTS_REQTOF9_Pos) /*!< PDMA_T::INTSTS: REQTOF9 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_ABTSTS_ABTIF9_Pos (9) /*!< PDMA_T::ABTSTS: ABTIF9 Position */ +#define PDMA_ABTSTS_ABTIF9_Msk (0x1ul << PDMA_ABTSTS_ABTIF9_Pos) /*!< PDMA_T::ABTSTS: ABTIF9 Mask */ + +#define PDMA_ABTSTS_ABTIF10_Pos (10) /*!< PDMA_T::ABTSTS: ABTIF10 Position */ +#define PDMA_ABTSTS_ABTIF10_Msk (0x1ul << PDMA_ABTSTS_ABTIF10_Pos) /*!< PDMA_T::ABTSTS: ABTIF10 Mask */ + +#define PDMA_ABTSTS_ABTIF11_Pos (11) /*!< PDMA_T::ABTSTS: ABTIF11 Position */ +#define PDMA_ABTSTS_ABTIF11_Msk (0x1ul << PDMA_ABTSTS_ABTIF11_Pos) /*!< PDMA_T::ABTSTS: ABTIF11 Mask */ + +#define PDMA_ABTSTS_ABTIF12_Pos (12) /*!< PDMA_T::ABTSTS: ABTIF12 Position */ +#define PDMA_ABTSTS_ABTIF12_Msk (0x1ul << PDMA_ABTSTS_ABTIF12_Pos) /*!< PDMA_T::ABTSTS: ABTIF12 Mask */ + +#define PDMA_ABTSTS_ABTIF13_Pos (13) /*!< PDMA_T::ABTSTS: ABTIF13 Position */ +#define PDMA_ABTSTS_ABTIF13_Msk (0x1ul << PDMA_ABTSTS_ABTIF13_Pos) /*!< PDMA_T::ABTSTS: ABTIF13 Mask */ + +#define PDMA_ABTSTS_ABTIF14_Pos (14) /*!< PDMA_T::ABTSTS: ABTIF14 Position */ +#define PDMA_ABTSTS_ABTIF14_Msk (0x1ul << PDMA_ABTSTS_ABTIF14_Pos) /*!< PDMA_T::ABTSTS: ABTIF14 Mask */ + +#define PDMA_ABTSTS_ABTIF15_Pos (15) /*!< PDMA_T::ABTSTS: ABTIF15 Position */ +#define PDMA_ABTSTS_ABTIF15_Msk (0x1ul << PDMA_ABTSTS_ABTIF15_Pos) /*!< PDMA_T::ABTSTS: ABTIF15 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_TDSTS_TDIF9_Pos (9) /*!< PDMA_T::TDSTS: TDIF9 Position */ +#define PDMA_TDSTS_TDIF9_Msk (0x1ul << PDMA_TDSTS_TDIF9_Pos) /*!< PDMA_T::TDSTS: TDIF9 Mask */ + +#define PDMA_TDSTS_TDIF10_Pos (10) /*!< PDMA_T::TDSTS: TDIF10 Position */ +#define PDMA_TDSTS_TDIF10_Msk (0x1ul << PDMA_TDSTS_TDIF10_Pos) /*!< PDMA_T::TDSTS: TDIF10 Mask */ + +#define PDMA_TDSTS_TDIF11_Pos (11) /*!< PDMA_T::TDSTS: TDIF11 Position */ +#define PDMA_TDSTS_TDIF11_Msk (0x1ul << PDMA_TDSTS_TDIF11_Pos) /*!< PDMA_T::TDSTS: TDIF11 Mask */ + +#define PDMA_TDSTS_TDIF12_Pos (12) /*!< PDMA_T::TDSTS: TDIF12 Position */ +#define PDMA_TDSTS_TDIF12_Msk (0x1ul << PDMA_TDSTS_TDIF12_Pos) /*!< PDMA_T::TDSTS: TDIF12 Mask */ + +#define PDMA_TDSTS_TDIF13_Pos (13) /*!< PDMA_T::TDSTS: TDIF13 Position */ +#define PDMA_TDSTS_TDIF13_Msk (0x1ul << PDMA_TDSTS_TDIF13_Pos) /*!< PDMA_T::TDSTS: TDIF13 Mask */ + +#define PDMA_TDSTS_TDIF14_Pos (14) /*!< PDMA_T::TDSTS: TDIF14 Position */ +#define PDMA_TDSTS_TDIF14_Msk (0x1ul << PDMA_TDSTS_TDIF14_Pos) /*!< PDMA_T::TDSTS: TDIF14 Mask */ + +#define PDMA_TDSTS_TDIF15_Pos (15) /*!< PDMA_T::TDSTS: TDIF15 Position */ +#define PDMA_TDSTS_TDIF15_Msk (0x1ul << PDMA_TDSTS_TDIF15_Pos) /*!< PDMA_T::TDSTS: TDIF15 Mask */ + +#define PDMA_ALIGN_ALIGNn_Pos (0) /*!< PDMA_T::ALIGN: ALIGNn Position */ +#define PDMA_ALIGN_ALIGNn_Msk (0xfffful << 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 (0xfffful << 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_TOC2_3_TOC2_Pos (0) /*!< PDMA_T::TOC2_3: TOC2 Position */ +#define PDMA_TOC2_3_TOC2_Msk (0xfffful << PDMA_TOC2_3_TOC2_Pos) /*!< PDMA_T::TOC2_3: TOC2 Mask */ + +#define PDMA_TOC2_3_TOC3_Pos (16) /*!< PDMA_T::TOC2_3: TOC3 Position */ +#define PDMA_TOC2_3_TOC3_Msk (0xfffful << PDMA_TOC2_3_TOC3_Pos) /*!< PDMA_T::TOC2_3: TOC3 Mask */ + +#define PDMA_TOC4_5_TOC4_Pos (0) /*!< PDMA_T::TOC4_5: TOC4 Position */ +#define PDMA_TOC4_5_TOC4_Msk (0xfffful << PDMA_TOC4_5_TOC4_Pos) /*!< PDMA_T::TOC4_5: TOC4 Mask */ + +#define PDMA_TOC4_5_TOC5_Pos (16) /*!< PDMA_T::TOC4_5: TOC5 Position */ +#define PDMA_TOC4_5_TOC5_Msk (0xfffful << PDMA_TOC4_5_TOC5_Pos) /*!< PDMA_T::TOC4_5: TOC5 Mask */ + +#define PDMA_TOC6_7_TOC6_Pos (0) /*!< PDMA_T::TOC6_7: TOC6 Position */ +#define PDMA_TOC6_7_TOC6_Msk (0xfffful << PDMA_TOC6_7_TOC6_Pos) /*!< PDMA_T::TOC6_7: TOC6 Mask */ + +#define PDMA_TOC6_7_TOC7_Pos (16) /*!< PDMA_T::TOC6_7: TOC7 Position */ +#define PDMA_TOC6_7_TOC7_Msk (0xfffful << PDMA_TOC6_7_TOC7_Pos) /*!< PDMA_T::TOC6_7: TOC7 Mask */ + +#define PDMA_TOC8_9_TOC8_Pos (0) /*!< PDMA_T::TOC8_9: TOC8 Position */ +#define PDMA_TOC8_9_TOC8_Msk (0xfffful << PDMA_TOC8_9_TOC8_Pos) /*!< PDMA_T::TOC8_9: TOC8 Mask */ + +#define PDMA_TOC8_9_TOC9_Pos (16) /*!< PDMA_T::TOC8_9: TOC9 Position */ +#define PDMA_TOC8_9_TOC9_Msk (0xfffful << PDMA_TOC8_9_TOC9_Pos) /*!< PDMA_T::TOC8_9: TOC9 Mask */ + +#define PDMA_CHRST_CHnRST_Pos (0) /*!< PDMA_T::CHRST: CHnRST Position */ +#define PDMA_CHRST_CHnRST_Msk (0xfffful << 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 (0x7ful << 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 (0x7ful << 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 (0x7ful << 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 (0x7ful << 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 (0x7ful << 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 (0x7ful << 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 (0x7ful << 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 (0x7ful << PDMA_REQSEL4_7_REQSRC7_Pos) /*!< PDMA_T::REQSEL4_7: REQSRC7 Mask */ + +#define PDMA_REQSEL8_11_REQSRC8_Pos (0) /*!< PDMA_T::REQSEL8_11: REQSRC8 Position */ +#define PDMA_REQSEL8_11_REQSRC8_Msk (0x7ful << PDMA_REQSEL8_11_REQSRC8_Pos) /*!< PDMA_T::REQSEL8_11: REQSRC8 Mask */ + +#define PDMA_REQSEL8_11_REQSRC9_Pos (8) /*!< PDMA_T::REQSEL8_11: REQSRC9 Position */ +#define PDMA_REQSEL8_11_REQSRC9_Msk (0x7ful << PDMA_REQSEL8_11_REQSRC9_Pos) /*!< PDMA_T::REQSEL8_11: REQSRC9 Mask */ + +#define PDMA_REQSEL8_11_REQSRC10_Pos (16) /*!< PDMA_T::REQSEL8_11: REQSRC10 Position */ +#define PDMA_REQSEL8_11_REQSRC10_Msk (0x7ful << PDMA_REQSEL8_11_REQSRC10_Pos) /*!< PDMA_T::REQSEL8_11: REQSRC10 Mask */ + +#define PDMA_REQSEL8_11_REQSRC11_Pos (24) /*!< PDMA_T::REQSEL8_11: REQSRC11 Position */ +#define PDMA_REQSEL8_11_REQSRC11_Msk (0x7ful << PDMA_REQSEL8_11_REQSRC11_Pos) /*!< PDMA_T::REQSEL8_11: REQSRC11 Mask */ + +#define PDMA_REQSEL12_15_REQSRC12_Pos (0) /*!< PDMA_T::REQSEL12_15: REQSRC12 Position */ +#define PDMA_REQSEL12_15_REQSRC12_Msk (0x7ful << PDMA_REQSEL12_15_REQSRC12_Pos) /*!< PDMA_T::REQSEL12_15: REQSRC12 Mask */ + +#define PDMA_REQSEL12_15_REQSRC13_Pos (8) /*!< PDMA_T::REQSEL12_15: REQSRC13 Position */ +#define PDMA_REQSEL12_15_REQSRC13_Msk (0x7ful << PDMA_REQSEL12_15_REQSRC13_Pos) /*!< PDMA_T::REQSEL12_15: REQSRC13 Mask */ + +#define PDMA_REQSEL12_15_REQSRC14_Pos (16) /*!< PDMA_T::REQSEL12_15: REQSRC14 Position */ +#define PDMA_REQSEL12_15_REQSRC14_Msk (0x7ful << PDMA_REQSEL12_15_REQSRC14_Pos) /*!< PDMA_T::REQSEL12_15: REQSRC14 Mask */ + +#define PDMA_REQSEL12_15_REQSRC15_Pos (24) /*!< PDMA_T::REQSEL12_15: REQSRC15 Position */ +#define PDMA_REQSEL12_15_REQSRC15_Msk (0x7ful << PDMA_REQSEL12_15_REQSRC15_Pos) /*!< PDMA_T::REQSEL12_15: REQSRC15 Mask */ + +#define PDMA_STCRn_STC_Pos (0) /*!< PDMA_T::STCRn: STC Position */ +#define PDMA_STCRn_STC_Msk (0xfffful << PDMA_STCRn_STC_Pos) /*!< PDMA_T::STCRn: STC Mask */ + +#define PDMA_ASOCRn_SASOL_Pos (0) /*!< PDMA_T::ASOCRn: SASOL Position */ +#define PDMA_ASOCRn_SASOL_Msk (0xfffful << PDMA_ASOCRn_SASOL_Pos) /*!< PDMA_T::ASOCRn: SASOL Mask */ + +#define PDMA_ASOCRn_DASOL_Pos (16) /*!< PDMA_T::ASOCRn: DASOL Position */ +#define PDMA_ASOCRn_DASOL_Msk (0xfffful << PDMA_ASOCRn_DASOL_Pos) /*!< PDMA_T::ASOCRn: DASOL Mask */ + +/**@}*/ /* PDMA_CONST */ +/**@}*/ /* end of PDMA register group */ +/**@}*/ /* end of REGISTER group */ + +#define PDMA0 ((PDMA_T *) PDMA0_BA) +#define PDMA1 ((PDMA_T *) PDMA1_BA) + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup PDMA_Driver PDMA Driver + @{ +*/ + +/** @addtogroup PDMA_EXPORTED_CONSTANTS PDMA Exported Constants + @{ +*/ +#define PDMA_CH_MAX 10UL /*!< 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 = (1 << ((u32Ch) + 8)))) + +/** + * @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 & (1 << (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)-1) << 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 = (1 << (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 = (1 << (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); +void PDMA_SetStride(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32DestLen, uint32_t u32SrcLen, uint32_t u32TransCount); + + +/*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group PDMA_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_PDMA_H__ */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h new file mode 100644 index 0000000000..4283ee32eb --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h @@ -0,0 +1,271 @@ +/**************************************************************************//** + * @file pwm.h + * @version V1.00 + * $Revision: 3 $ + * $Date: 15/05/19 10:16a $ + * @brief NUC980 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 "nuc980.h" +#include "nu_sys.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_OFFSET 0xc ///< each channel has 3 control registers which occupies 12 bytes + +// Timer channel identity information +#define PWM_TIMER_NUM 8 ///< Total PWM channel count +#define PWM_TIMER_MIN 0 ///< Min PWM channel number +#define PWM_TIMER_MAX 7 ///< Max PWM channel number +#define PWM0_TIMER0 0 ///< PWM0 channel 0 +#define PWM0_TIMER1 1 ///< PWM0 channel 1 +#define PWM0_TIMER2 2 ///< PWM0 channel 2 +#define PWM0_TIMER3 3 ///< PWM0 channel 3 +#define PWM1_TIMER0 4 ///< PWM1 channel 0 +#define PWM1_TIMER1 5 ///< PWM1 channel 1 +#define PWM1_TIMER2 6 ///< PWM1 channel 2 +#define PWM1_TIMER3 7 ///< PWM1 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 PWM00_GPF5 0 ///< PWM00 output on GPF5 +#define PWM01_GPF6 1 ///< PWM01 output on GPF6 +#define PWM02_GPF7 2 ///< PWM02 output on GPF7 +#define PWM03_GPF8 3 ///< PWM03 output on GPF8 +#define PWM00_GPG0 4 ///< PWM00 output on GPG0 +#define PWM01_GPG1 5 ///< PWM01 output on GPG1 +#define PWM02_GPG2 6 ///< PWM02 output on GPG2 +#define PWM03_GPG3 7 ///< PWM03 output on GPG3 +#define PWM00_GPD12 8 ///< PWM00 output on GPD12 +#define PWM01_GPD13 9 ///< PWM01 output on GPD13 +#define PWM02_GPD14 10 ///< PWM02 output on GPD14 +#define PWM03_GPD15 11 ///< PWM03 output on GPD15 +#define PWM00_GPG10 12 ///< PWM00 output on GPG10 +#define PWM01_GPA15 13 ///< PWM01 output on GPA15 +#define PWM02_GPA14 14 ///< PWM02 output on GPA14 +#define PWM03_GPA13 15 ///< PWM03 output on GPA13 +#define PWM02_GPB13 16 ///< PWM02 output on GPB13 + +#define PWM10_GPB12 17 ///< PWM10 output on GPB12 +#define PWM11_GPB11 18 ///< PWM11 output on GPB11 +#define PWM12_GPB10 19 ///< PWM12 output on GPB10 +#define PWM13_GPB9 20 ///< PWM13 output on GPB9 +#define PWM10_GPG6 21 ///< PWM10 output on GPG6 +#define PWM11_GPG7 22 ///< PWM11 output on GPG7 +#define PWM12_GPG8 23 ///< PWM12 output on GPG8 +#define PWM13_GPG9 24 ///< PWM13 output on GPG9 +#define PWM10_GPG11 25 ///< PWM10 output on GPG11 +#define PWM11_GPG12 26 ///< PWM11 output on GPG12 +#define PWM12_GPG13 27 ///< PWM12 output on GPG13 +#define PWM13_GPG14 28 ///< PWM13 output on GPG14 +#define PWM10_GPF9 29 ///< PWM10 output on GPF9 +#define PWM11_GPF10 30 ///< PWM11 output on GPF10 +#define PWM12_GPE10 31 ///< PWM12 output on GPE10 +#define PWM13_GPE12 32 ///< PWM13 output on GPE12 + +#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 PWM_EXPORTED_CONSTANTS */ + +/// @cond HIDDEN_SYMBOLS +/** @addtogroup 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 PWM_EXPORTED_STRUCTS */ +/// @endcond /* HIDDEN_SYMBOLS */ + +/** @addtogroup PWM_EXPORTED_FUNCTIONS PWM Exported Functions + @{ +*/ + +// function definition +INT pwmInit(const INT nTimerIdentity); +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 PWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group PWM_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_PWM_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_qspi.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_qspi.h new file mode 100644 index 0000000000..92a952ff42 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_qspi.h @@ -0,0 +1,929 @@ +/**************************************************************************//** + * @file qspi.h + * @brief NUC980 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 REGISTER Control Register + @{ +*/ + +/** + @addtogroup QSPI 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] |QSPIEN |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 QSPIEN (QSPIx_CTL[0]) and confirm the QSPIENSTS (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 (Only Supported in QSPI0) + * | | |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 (Only Supported in QSPI0) + * | | |0 = Dual I/O mode Disabled. + * | | |1 = Dual I/O mode Enabled. + * |[22] |QUADIOEN |Quad I/O Mode Enable Bit (Only Supported in QSPI0) + * | | |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. + * | | |where + * | | |is the peripheral clock source, which is defined in the clock control register, CLK_CLKSEL2. + * @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 (Only Supported in QSPI0) + * | | |Slave 3-wire mode is only available in QSPI0 + * | | |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 (Only Supported in QSPI0) + * | | |0 = Slave mode time-out interrupt Disabled. + * | | |1 = Slave mode time-out interrupt Enabled. + * |[6] |SLVTORST |Slave Mode Time-out Reset Control (Only Supported in QSPI0) + * | | |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 (Only Supported in QSPI0) + * | | |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 |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 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 listing are 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. + * | | |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 (Only Supported in QSPI0) + * | | |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] |QSPIENSTS |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 4-level transmit FIFO buffers + * | | |The number of valid bits depends on the setting of DWIDTH (QSPIx_CTL[12:8]) in SPI mode. + * | | |In SPI mode, 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. + * | | |If WDWIDTH is set as 0x0, 0x1, or 0x3, all bits of this field are valid + * | | |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 + * | | |There are 4-level FIFO buffers in this controller + * | | |The data receive register holds the data received from QSPI data input pin + * | | |This is a read only 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 */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE0[2]; + /// @endcond //HIDDEN_SYMBOLS + __O uint32_t TX; /*!< [0x0020] QSPI Data Transmit Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE1[3]; + /// @endcond //HIDDEN_SYMBOLS + __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_QSPIEN_Pos (0) /*!< QSPI_T::CTL: QSPIEN Position */ +#define QSPI_CTL_QSPIEN_Msk (0x1ul << QSPI_CTL_QSPIEN_Pos) /*!< QSPI_T::CTL: QSPIEN 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_QSPIENSTS_Pos (15) /*!< QSPI_T::STATUS: QSPIENSTS Position */ +#define QSPI_STATUS_QSPIENSTS_Msk (0x1ul << QSPI_STATUS_QSPIENSTS_Pos) /*!< QSPI_T::STATUS: QSPIENSTS 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 */ + +#define QSPI0 ((QSPI_T *) QSPI0_BA) + +/** @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 (0x0U) /*!< 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 (0x0U) /*!< SS active low \hideinitializer */ + +/* QSPI Interrupt Mask */ +#define QSPI_UNIT_INT_MASK (0x001U) /*!< Unit transfer interrupt mask \hideinitializer */ +#define QSPI_SSACT_INT_MASK (0x002U) /*!< Slave selection signal active interrupt mask \hideinitializer */ +#define QSPI_SSINACT_INT_MASK (0x004U) /*!< Slave selection signal inactive interrupt mask \hideinitializer */ +#define QSPI_SLVUR_INT_MASK (0x008U) /*!< Slave under run interrupt mask \hideinitializer */ +#define QSPI_SLVBE_INT_MASK (0x010U) /*!< Slave bit count error interrupt mask \hideinitializer */ +#define QSPI_TXUF_INT_MASK (0x040U) /*!< Slave TX underflow interrupt mask \hideinitializer */ +#define QSPI_FIFO_TXTH_INT_MASK (0x080U) /*!< FIFO TX threshold interrupt mask \hideinitializer */ +#define QSPI_FIFO_RXTH_INT_MASK (0x100U) /*!< FIFO RX threshold interrupt mask \hideinitializer */ +#define QSPI_FIFO_RXOV_INT_MASK (0x200U) /*!< FIFO RX overrun interrupt mask \hideinitializer */ +#define QSPI_FIFO_RXTO_INT_MASK (0x400U) /*!< FIFO RX time-out interrupt mask \hideinitializer */ + +/* QSPI Status Mask */ +#define QSPI_BUSY_MASK (0x01U) /*!< Busy status mask \hideinitializer */ +#define QSPI_RX_EMPTY_MASK (0x02U) /*!< RX empty status mask \hideinitializer */ +#define QSPI_RX_FULL_MASK (0x04U) /*!< RX full status mask \hideinitializer */ +#define QSPI_TX_EMPTY_MASK (0x08U) /*!< TX empty status mask \hideinitializer */ +#define QSPI_TX_FULL_MASK (0x10U) /*!< TX full status mask \hideinitializer */ +#define QSPI_TXRX_RESET_MASK (0x20U) /*!< TX or RX reset status mask \hideinitializer */ +#define QSPI_QSPIEN_STS_MASK (0x40U) /*!< QSPIEN status mask \hideinitializer */ +#define QSPI_SSLINE_STS_MASK (0x80U) /*!< 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 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 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 SPI 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 QSPIEN (QSPI_CTL[0]) to enable QSPI controller. + * \hideinitializer + */ +#define QSPI_ENABLE(qspi) ((qspi)->CTL |= QSPI_CTL_QSPIEN_Msk) + +/** + * @brief Disable QSPI controller. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear QSPIEN (QSPI_CTL[0]) to disable QSPI controller. + * \hideinitializer + */ +#define QSPI_DISABLE(qspi) ((qspi)->CTL &= ~QSPI_CTL_QSPIEN_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 Dual 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 + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_rtc.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_rtc.h new file mode 100644 index 0000000000..a67820b0ef --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_rtc.h @@ -0,0 +1,445 @@ +/**************************************************************************//** + * @file rtc.h + * @version V3.00 + * @brief NUC980 series RTC driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_RTC_H__ +#define __NU_RTC_H__ + +#include +#include +#include +#include "nuc980.h" + + +/** @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 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_WAIT_COUNT 0xFFFFFFFFUL /*!< Initial Time-out Value \hideinitializer */ +#define RTC_YEAR2000 2000UL /*!< RTC Reference for compute year data \hideinitializer */ +#define RTC_FCR_REFERENCE 32761UL /*!< RTC Reference for frequency compensation \hideinitializer */ + +#define RTC_2POW10_CLK (0x0 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 RTC clock cycles \hideinitializer */ +#define RTC_2POW11_CLK (0x1 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 2 RTC clock cycles \hideinitializer */ +#define RTC_2POW12_CLK (0x2 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 4 RTC clock cycles \hideinitializer */ +#define RTC_2POW13_CLK (0x3 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 6 RTC clock cycles \hideinitializer */ +#define RTC_2POW14_CLK (0x4 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 8 RTC clock cycles \hideinitializer */ +#define RTC_2POW15_CLK (0x5 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 16 RTC clock cycles \hideinitializer */ +#define RTC_2POW16_CLK (0x6 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 32 RTC clock cycles \hideinitializer */ +#define RTC_2POW17_CLK (0x7 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 64 RTC clock cycles \hideinitializer */ + +#define REF_RANDOM_PATTERN 0x0 /*!< The new reference pattern is generated by random number generator when the reference pattern run out \hideinitializer */ +#define REF_PREVIOUS_PATTERN 0x1 /*!< The new reference pattern is repeated previous random value when the reference pattern run out \hideinitializer */ +#define REF_SEED 0x3 /*!< The new reference pattern is repeated from SEED (RTC_TAMPSEED[31:0]) when the reference pattern run out \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 */ + + +typedef struct +{ + uint32_t INIT; /*!< [0x0000] RTC Initiation Register */ + uint32_t RWEN; /*!< [0x0004] RTC Access Enable Register */ + uint32_t FREQADJ; /*!< [0x0008] RTC Frequency Compensation Register */ + uint32_t TIME; /*!< [0x000c] RTC Time Loading Register */ + uint32_t CAL; /*!< [0x0010] RTC Calendar Loading Register */ + uint32_t CLKFMT; /*!< [0x0014] RTC Time Scale Selection Register */ + uint32_t WEEKDAY; /*!< [0x0018] RTC Day of the Week Register */ + uint32_t TALM; /*!< [0x001c] RTC Time Alarm Register */ + uint32_t CALM; /*!< [0x0020] RTC Calendar Alarm Register */ + uint32_t LEAPYEAR; /*!< [0x0024] RTC Leap Year Indicator Register */ + uint32_t INTEN; /*!< [0x0028] RTC Interrupt Enable Register */ + uint32_t INTSTS; /*!< [0x002c] RTC Interrupt Status Register */ + uint32_t TICK; /*!< [0x0030] RTC Time Tick Register */ + uint32_t PWRCTL; /*!< [0x0034] RTC Power Control Register */ + uint32_t PWRCNT; /*!< [0x0038] RTC Power Control Counter Register */ + uint32_t RESERVE0; /*!< [0x003c] RTC Spare Functional Control Register */ + uint32_t SPR[16]; /*!< [0x0040] ~ [0x007c] RTC Spare Register 0 ~ 15 */ +} RTC_T; + +#define RTC_INIT_ACTIVE_Pos (0) /*!< RTC_T::INIT: INIT_ACTIVE Position */ +#define RTC_INIT_ACTIVE_Msk (0x1ul << RTC_INIT_ACTIVE_Pos) /*!< RTC_T::INIT: 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_RWEN_RWENF_Pos (16) /*!< RTC_T::RWEN: RWENF Position */ +#define RTC_RWEN_RWENF_Msk (0x1ul << RTC_RWEN_RWENF_Pos) /*!< RTC_T::RWEN: RWENF Mask */ + +#define RTC_RWEN_RTCBUSY_Pos (24) /*!< RTC_T::RWEN: RTCBUSY Position */ +#define RTC_RWEN_RTCBUSY_Msk (0x1ul << RTC_RWEN_RTCBUSY_Pos) /*!< RTC_T::RWEN: RTCBUSY Mask */ + +#define RTC_FREQADJ_FRACTION_Pos (0) /*!< RTC_T::FRACTION: FRACTION Position */ +#define RTC_FREQADJ_FRACTION_Msk (0x3ful << RTC_FREQADJ_FRACTION_Pos) /*!< RTC_T::FRACTION: FRACTION Mask */ + +#define RTC_INTEGER_FRACTION_Pos (8) /*!< RTC_T::INTEGER: INTEGER Position */ +#define RTC_INTEGER_FRACTION_Msk (0xful << RTC_FREQADJ_INTEGER_Pos) /*!< RTC_T::INTEGER: 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_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_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_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_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_RELALMIEN_Pos (4) /*!< RTC INTEN: RELALMIEN Position */ +#define RTC_INTEN_RELALMIEN_Msk (0x1ul << RTC_INTEN_RELALMIEN_Pos) /*!< RTC INTEN: RELALMIEN 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_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_REGWRBUSY_Pos (31) /*!< RTC INTSTS: REGWRBUSY Position */ +#define RTC_INTSTS_REGWRBUSY_Msk (0x1ul << RTC_INTSTS_REGWRBUSY_Pos) /*!< RTC INTSTS: REGWRBUSY 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_PWRCTL_ALARM_EN_Pos (3) +#define RTC_PWRCTL_ALARM_EN_Msk (0x1ul << RTC_PWRCTL_ALARM_EN_Pos) + +#define RTC_PWRCTL_REL_ALARM_EN_Pos (4) +#define RTC_PWRCTL_REL_ALARM_EN_Msk (0x1ul << RTC_PWRCTL_REL_ALARM_EN_Pos) + +#define RTC_PWRCTL_RELALM_TIME_Pos (16) +#define RTC_PWRCTL_RELALM_TIME_Msk (0xffful << RTC_PWRCTL_RELALM_TIME_Pos) + +#define RTC_SPR0_SPARE_Pos (0) /*!< RTC_T::SPR0: SPARE Position */ +#define RTC_SPR0_SPARE_Msk (0xfffffffful << RTC_SPR0_SPARE_Pos) /*!< RTC_T::SPR0: SPARE Mask */ + +#define RTC_SPR1_SPARE_Pos (0) /*!< RTC_T::SPR1: SPARE Position */ +#define RTC_SPR1_SPARE_Msk (0xfffffffful << RTC_SPR1_SPARE_Pos) /*!< RTC_T::SPR1: SPARE Mask */ + +#define RTC_SPR2_SPARE_Pos (0) /*!< RTC_T::SPR2: SPARE Position */ +#define RTC_SPR2_SPARE_Msk (0xfffffffful << RTC_SPR2_SPARE_Pos) /*!< RTC_T::SPR2: SPARE Mask */ + +#define RTC_SPR3_SPARE_Pos (0) /*!< RTC_T::SPR3: SPARE Position */ +#define RTC_SPR3_SPARE_Msk (0xfffffffful << RTC_SPR3_SPARE_Pos) /*!< RTC_T::SPR3: SPARE Mask */ + +#define RTC_SPR4_SPARE_Pos (0) /*!< RTC_T::SPR4: SPARE Position */ +#define RTC_SPR4_SPARE_Msk (0xfffffffful << RTC_SPR4_SPARE_Pos) /*!< RTC_T::SPR4: SPARE Mask */ + +#define RTC_SPR5_SPARE_Pos (0) /*!< RTC_T::SPR5: SPARE Position */ +#define RTC_SPR5_SPARE_Msk (0xfffffffful << RTC_SPR5_SPARE_Pos) /*!< RTC_T::SPR5: SPARE Mask */ + +#define RTC_SPR6_SPARE_Pos (0) /*!< RTC_T::SPR6: SPARE Position */ +#define RTC_SPR6_SPARE_Msk (0xfffffffful << RTC_SPR6_SPARE_Pos) /*!< RTC_T::SPR6: SPARE Mask */ + +#define RTC_SPR7_SPARE_Pos (0) /*!< RTC_T::SPR7: SPARE Position */ +#define RTC_SPR7_SPARE_Msk (0xfffffffful << RTC_SPR7_SPARE_Pos) /*!< RTC_T::SPR7: SPARE Mask */ + +#define RTC_SPR8_SPARE_Pos (0) /*!< RTC_T::SPR8: SPARE Position */ +#define RTC_SPR8_SPARE_Msk (0xfffffffful << RTC_SPR8_SPARE_Pos) /*!< RTC_T::SPR8: SPARE Mask */ + +#define RTC_SPR9_SPARE_Pos (0) /*!< RTC_T::SPR9: SPARE Position */ +#define RTC_SPR9_SPARE_Msk (0xfffffffful << RTC_SPR9_SPARE_Pos) /*!< RTC_T::SPR9: SPARE Mask */ + +#define RTC_SPR10_SPARE_Pos (0) /*!< RTC_T::SPR10: SPARE Position */ +#define RTC_SPR10_SPARE_Msk (0xfffffffful << RTC_SPR10_SPARE_Pos) /*!< RTC_T::SPR10: SPARE Mask */ + +#define RTC_SPR11_SPARE_Pos (0) /*!< RTC_T::SPR11: SPARE Position */ +#define RTC_SPR11_SPARE_Msk (0xfffffffful << RTC_SPR11_SPARE_Pos) /*!< RTC_T::SPR11: SPARE Mask */ + +#define RTC_SPR12_SPARE_Pos (0) /*!< RTC_T::SPR12: SPARE Position */ +#define RTC_SPR12_SPARE_Msk (0xfffffffful << RTC_SPR12_SPARE_Pos) /*!< RTC_T::SPR12: SPARE Mask */ + +#define RTC_SPR13_SPARE_Pos (0) /*!< RTC_T::SPR13: SPARE Position */ +#define RTC_SPR13_SPARE_Msk (0xfffffffful << RTC_SPR13_SPARE_Pos) /*!< RTC_T::SPR13: SPARE Mask */ + +#define RTC_SPR14_SPARE_Pos (0) /*!< RTC_T::SPR14: SPARE Position */ +#define RTC_SPR14_SPARE_Msk (0xfffffffful << RTC_SPR14_SPARE_Pos) /*!< RTC_T::SPR14: SPARE Mask */ + +#define RTC_SPR15_SPARE_Pos (0) /*!< RTC_T::SPR15: SPARE Position */ +#define RTC_SPR15_SPARE_Msk (0xfffffffful << RTC_SPR15_SPARE_Pos) /*!< RTC_T::SPR15: SPARE Mask */ + + +#define RTC ((RTC_T *) RTC_BA) + +/** @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 Read Spare Register + * + * @param[in] u32RegNum The spare register number, 0~19. + * + * @return Spare register content + * + * @details Read the specify spare register content. + * @note The returned value is valid only when SPRRDY(SPRCTL[7] SPR Register Ready) bit is set. \n + * And its controlled by RTC Access Enable Register. + * \hideinitializer + */ +#define RTC_READ_SPARE_REGISTER(u32RegNum) (RTC->SPR[(u32RegNum)]) + +/** + * @brief Write Spare Register + * + * @param[in] u32RegNum The spare register number, 0~19. + * @param[in] u32RegValue The spare register value. + * + * @return None + * + * @details Write specify data to spare register. + * @note This macro is effect only when SPRRDY(SPRCTL[7] SPR Register Ready) bit is set. \n + * And its controlled by RTC Access Enable Register(RTC_RWEN). + * \hideinitializer + */ +#define RTC_WRITE_SPARE_REGISTER(u32RegNum, u32RegValue) (RTC->SPR[(u32RegNum)] = (u32RegValue)) + +/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */ +void RTC_WaitAccessEnable(void); +void RTC_Check(void); + +void RTC_Open(S_RTC_TIME_DATA_T *sPt); +void RTC_Close(void); +void RTC_32KCalibration(int32_t i32FrequencyX100); +void RTC_GetDateAndTime(S_RTC_TIME_DATA_T *sPt); +void RTC_GetAlarmDateAndTime(S_RTC_TIME_DATA_T *sPt); +void RTC_SetDateAndTime(S_RTC_TIME_DATA_T *sPt); +void RTC_SetAlarmDateAndTime(S_RTC_TIME_DATA_T *sPt); +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, uint32_t u32DayOfWeek); +void RTC_SetAlarmTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm); +uint32_t RTC_GetDayOfWeek(void); +void RTC_SetTickPeriod(uint32_t u32TickSelection); +void RTC_EnableInt(uint32_t u32IntFlagMask); +void RTC_DisableInt(uint32_t u32IntFlagMask); +void RTC_EnableSpareAccess(void); +void RTC_DisableSpareRegister(void); + +/*@}*/ /* end of group RTC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group RTC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + +#endif /* __NU_RTC_H__ */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sc.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sc.h new file mode 100644 index 0000000000..935de24b93 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sc.h @@ -0,0 +1,425 @@ +/**************************************************************************//** + * @file sc.h + * @brief NUC980 Smartcard (SC) driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_SC_H__ +#define __NU_SC_H__ +#include "nuc980.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SC_Driver SC Driver + @{ +*/ + +/** @addtogroup SC_EXPORTED_CONSTANTS SC Exported Constants + @{ +*/ +#define SC_INTERFACE_NUM 2 /*!< Smartcard interface numbers */ /* NUC980 series has two SC interface */ +#define SC_PIN_STATE_HIGH 1 /*!< Smartcard pin status high */ +#define SC_PIN_STATE_LOW 0 /*!< Smartcard pin status low */ +#define SC_PIN_STATE_IGNORE 0xFFFFFFFF /*!< Ignore pin status */ +#define SC_CLK_ON 1 /*!< Smartcard clock on */ +#define SC_CLK_OFF 0 /*!< Smartcard clock off */ + +#define SC_TMR_MODE_0 (0ul << 24) /*! + +#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_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_RTOIEN_Pos (12) /*!< SDH_T::INTEN: RTOIEN Position */ +#define SDH_INTEN_RTOIEN_Msk (0x1ul << SDH_INTEN_RTOIEN_Pos) /*!< SDH_T::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_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_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_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 SDH_EXPORTED_CONSTANTS */ + +/** @addtogroup SDH_EXPORTED_TYPEDEF SDH Exported Type Defines + @{ +*/ +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 SDH_EXPORTED_TYPEDEF */ + +/// @cond HIDDEN_SYMBOLS +extern SDH_INFO_T SD0, SD1; + +/// @endcond HIDDEN_SYMBOLS + +/** @addtogroup SDH_EXPORTED_FUNCTIONS SDH Exported Functions + @{ +*/ + +/** + * @brief Enable 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_CDIEN_Msk / + * \ref SDH_INTEN_CDSRC_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_CDIEN_Msk / + * \ref SDH_INTEN_RTOIEN_Msk / \ref SDH_INTEN_DITOIEN_Msk / \ref SDH_INTEN_WKIEN_Msk / \ref SDH_INTEN_CDSRC_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_CDIF_Msk \ref SDH_INTSTS_RTOIF_Msk / + * \ref SDH_INTSTS_DITOIF_Msk / \ref SDH_INTSTS_CDSTS_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_CDIF_Msk / + * \ref SDH_INTSTS_RTOIF_Msk / \ref SDH_INTSTS_DITOIF_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 SDH_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SDH_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#endif //end of __NU_SDH_H__ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_spi.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_spi.h new file mode 100644 index 0000000000..fd1b162292 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_spi.h @@ -0,0 +1,852 @@ +/**************************************************************************//** + * @file spi.h + * @brief NUC980 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 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 .... 0.5 SPICLK clock cycle. + * | | |SUSPITV = 0x1 .... 1.5 SPICLK clock cycle. + * | | |..... + * | | |SUSPITV = 0xE .... 14.5 SPICLK clock cycle. + * | | |SUSPITV = 0xF .... 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. + * | | |Note: For SPI1~SPI4, this bit field will decide the depth of TX/RX FIFO configuration in SPI mode + * | | |Therefore, changing this bit field will clear TX/RX FIFO by hardware automatically in SPI1~SPI4. + * |[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 in half-duplex transfer. + * | | |0 = SPI operates in full-duplex transfer. + * | | |1 = SPI 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, SPI Master will generate SPI bus clock continuously for receiving data bit from SPI slave device and assert the BUSY status. + * | | |0 = Receive-only mode Disabled. + * | | |1 = Receive-only mode Enabled. + * |[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 in half-duplex transfer and Dual/Quad 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 + * | :----: | :----: | :---- | + * |[8: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. + * | | |where + * | | |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 = Receive PDMA function Disabled. + * | | |1 = Receive 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. + * | | |Note: If TX underflow event occurs in SPI Slave mode, this bit can be used to make SPI 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 |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 no 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 + * | | |When TX underflow event occurs in Slave mode, TXUFIF (SPIx_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 + * | | |For SPI1~SPI4, the MSB of this bit field is only meaningful while SPI mode 8~16 bits of data length. + * |[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 + * | | |For SPI1~SPI4, 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 TXEMPTY = 0. + * | | |b + * | | |For SPI Master mode, SPIx_CTL[0] = 1 and 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. + * | | |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 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 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 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 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. + * | | |In 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[23: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 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. + */ + __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 */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE0[2]; + /// @endcond //HIDDEN_SYMBOLS + __O uint32_t TX; /*!< [0x0020] SPI Data Transmit Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE1[3]; + /// @endcond //HIDDEN_SYMBOLS + __I uint32_t RX; /*!< [0x0030] SPI Data Receive Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE2[11]; + /// @endcond //HIDDEN_SYMBOLS + +} 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_SSCTL_SLVTOCNT_Pos (16) /*!< SPI_T::SSCTL: SLVTOCNT Position */ +#define SPI_SSCTL_SLVTOCNT_Msk (0xfffful << SPI_SSCTL_SLVTOCNT_Pos) /*!< SPI_T::SSCTL: SLVTOCNT 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 */ + +/**@}*/ /* SPI_CONST */ +/**@}*/ /* end of SPI register group */ +/**@}*/ /* end of REGISTER group */ + +#define SPI0 ((SPI_T *) SPI0_BA) +#define SPI1 ((SPI_T *) SPI1_BA) + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SPI_Driver SPI Driver + @{ +*/ + +/** @addtogroup SPI_EXPORTED_CONSTANTS SPI Exported Constants + @{ +*/ +#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 (0x0U) /*!< 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 (0x0U) /*!< SS active low \hideinitializer */ + +/* SPI Interrupt Mask */ +#define SPI_UNIT_INT_MASK (0x001U) /*!< Unit transfer interrupt mask \hideinitializer */ +#define SPI_SSACT_INT_MASK (0x002U) /*!< Slave selection signal active interrupt mask \hideinitializer */ +#define SPI_SSINACT_INT_MASK (0x004U) /*!< Slave selection signal inactive interrupt mask \hideinitializer */ +#define SPI_SLVUR_INT_MASK (0x008U) /*!< Slave under run interrupt mask \hideinitializer */ +#define SPI_SLVBE_INT_MASK (0x010U) /*!< Slave bit count error interrupt mask \hideinitializer */ +#define SPI_TXUF_INT_MASK (0x040U) /*!< Slave TX underflow interrupt mask \hideinitializer */ +#define SPI_FIFO_TXTH_INT_MASK (0x080U) /*!< FIFO TX threshold interrupt mask \hideinitializer */ +#define SPI_FIFO_RXTH_INT_MASK (0x100U) /*!< FIFO RX threshold interrupt mask \hideinitializer */ +#define SPI_FIFO_RXOV_INT_MASK (0x200U) /*!< FIFO RX overrun interrupt mask \hideinitializer */ +#define SPI_FIFO_RXTO_INT_MASK (0x400U) /*!< FIFO RX time-out interrupt mask \hideinitializer */ + +/* SPI Status Mask */ +#define SPI_BUSY_MASK (0x01U) /*!< Busy status mask \hideinitializer */ +#define SPI_RX_EMPTY_MASK (0x02U) /*!< RX empty status mask \hideinitializer */ +#define SPI_RX_FULL_MASK (0x04U) /*!< RX full status mask \hideinitializer */ +#define SPI_TX_EMPTY_MASK (0x08U) /*!< TX empty status mask \hideinitializer */ +#define SPI_TX_FULL_MASK (0x10U) /*!< TX full status mask \hideinitializer */ +#define SPI_TXRX_RESET_MASK (0x20U) /*!< TX or RX reset status mask \hideinitializer */ +#define SPI_SPIEN_STS_MASK (0x40U) /*!< SPIEN status mask \hideinitializer */ +#define SPI_SSLINE_STS_MASK (0x80U) /*!< SPIx_SS line status mask \hideinitializer */ + +/*@}*/ /* end of group SPI_EXPORTED_CONSTANTS */ + + +/** @addtogroup SPI_EXPORTED_FUNCTIONS SPI Exported Functions + @{ +*/ + +/** + * @brief Clear the unit transfer interrupt flag. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Write 1 to UNITIF bit of SPI_STATUS register to clear the unit transfer interrupt flag. + * \hideinitializer + */ +#define SPI_CLR_UNIT_TRANS_INT_FLAG(spi) ((spi)->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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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]). + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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). + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#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. + * \hideinitializer + */ +#define SPI_DISABLE(spi) ((spi)->CTL &= ~SPI_CTL_SPIEN_Msk) + + +/* 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); +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); + +/*@}*/ /* end of group SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sys.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sys.h new file mode 100644 index 0000000000..2308cb1938 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_sys.h @@ -0,0 +1,838 @@ +/**************************************************************************//** + * @file sys.h + * @brief SYS driver header file + * + * 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 + @{ +*/ + + +/** + * @details Interrupt Number Definition. + */ +typedef enum IRQn +{ + IRQ_WDT = 1, // Watch Dog Timer + IRQ_WWDT = 2, // Windowed-WDT Interrupt + IRQ_LVD = 3, // LVD Interrupt + IRQ_EXTI0 = 4, // External Interrupt 0 + IRQ_EXTI1 = 5, // External Interrupt 1 + IRQ_EXTI2 = 6, // External Interrupt 2 + IRQ_EXTI3 = 7, // External Interrupt 3 + IRQ_GPA = 8, // GPA Interrupt + IRQ_GPB = 9, // GPB Interrupt + IRQ_GPC = 10, // GPC Interrupt + IRQ_GPD = 11, // GPD Interrupt + IRQ_I2S = 12, // I2S Interrupt + IRQ_CAP0 = 14, // Sensor Interface Controller Interrupt + IRQ_RTC = 15, // RTC interrupt + IRQ_TIMER0 = 16, // Timer 0 interrupt + IRQ_TIMER1 = 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_PDMA0 = 25, // PDMA Channel 0 Interrupt + IRQ_PDMA1 = 26, // PDMA Channel 1 Interrupt + IRQ_SDH = 27, // SD Host Interrupt + IRQ_FMI = 28, // NAND/eMMC Interrupt + IRQ_UDC = 29, // USB Device Controller Interrupt + IRQ_TIMER2 = 30, // Timer 2 interrupt + IRQ_TIMER3 = 31, // Timer 3 interrupt + IRQ_TIMER4 = 32, // Timer 4 interrupt + IRQ_CAP1 = 33, // VCAP1 Engine Interrupt + IRQ_TIMER5 = 34, // Timer 5 interrupt + IRQ_CRYPTO = 35, // CRYPTO Engine 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_CAN3 = 42, // CAN 3 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_I2C2 = 47, // I2C 2 interrupt + IRQ_I2C3 = 48, // I2C 3 interrupt + IRQ_GPE = 49, // GPE interrupt + IRQ_SPI1 = 50, // SPI 1 interrupt + IRQ_QSPI0 = 51, // QSPI 0 interrupt + IRQ_SPI0 = 52, // SPI 0 interrupt + IRQ_I2C0 = 53, // I2C 0 Interrupt + IRQ_I2C1 = 54, // I2C 1 Interrupt + IRQ_SMC0 = 55, // SmartCard 0 Interrupt + IRQ_SMC1 = 56, // SmartCard 1 Interrupt + IRQ_GPF = 57, // GPF interrupt + IRQ_CAN0 = 58, // CAN 0 interrupt + IRQ_CAN1 = 59, // CAN 1 interrupt + IRQ_PWM0 = 60, // PWM 0 interrupt + IRQ_PWM1 = 61, // PWM 1 interrupt + IRQ_CAN2 = 62, // CAN 2 interrupt + IRQ_GPG = 63, // GPG interrupt +} +IRQn_Type; + +/* Define constants for use AIC in service parameters. */ +#define SYS_SWI 0 +#define SYS_D_ABORT 1 +#define SYS_I_ABORT 2 +#define SYS_UNDEFINE 3 + +/* 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 */ + + +/* 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_HCLK = 4, /*!< HCLK1 clock */ + SYS_PCLK01 = 5, /*!< HCLK234 clock */ + SYS_PCLK2 = 6, /*!< PCLK clock */ + SYS_CPU = 7, /*!< CPU clock */ + +} CLK_Type; + +/* 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 constants for use Cache in service parameters. */ +#define I_CACHE 6 +#define D_CACHE 7 +#define I_D_CACHE 8 + + +/// @endcond HIDDEN_SYMBOLS + +/*@}*/ /* end of group SYS_EXPORTED_CONSTANTS */ + +/*---------------------- System Manger Controller -------------------------*/ +/** + @addtogroup SYS System Manger Controller(SYS) + Memory Mapped Structure for SYS Controller +@{ */ + +#define SYS ((SYS_T *) SYS_BA) + +typedef struct +{ + __I uint32_t PDID; /* Offset: 0x00 */ + __IO uint32_t PWRON; /* Offset: 0x04 */ + __IO uint32_t ARBCON; /* Offset: 0x08 */ + __I uint32_t RESERVE0[5]; + __IO uint32_t LVRDCR; /* Offset: 0x20 */ + __I uint32_t RESERVE1[3]; + __IO uint32_t MISCFCR; /* Offset: 0x30 */ + __I uint32_t RESERVE2[3]; + __IO uint32_t MISCIER; /* Offset: 0x40 */ + __IO uint32_t MISCISR; /* Offset: 0x44 */ + __I uint32_t RESERVE3[2]; + __IO uint32_t WKUPSER0; /* Offset: 0x50 */ + __IO uint32_t WKUPSER1; /* Offset: 0x54 */ + __IO uint32_t WKUPSSR0; /* Offset: 0x58 */ + __IO uint32_t WKUPSSR1; /* Offset: 0x5C */ + __IO uint32_t AHBIPRST; /* Offset: 0x60 */ + __IO uint32_t APBIPRST0; /* Offset: 0x64 */ + __IO uint32_t APBIPRST1; /* Offset: 0x68 */ + __IO uint32_t RSTSTS; /* Offset: 0x6C */ + __IO uint32_t GPA_MFPL; /* Offset: 0x70 */ + __IO uint32_t GPA_MFPH; /* Offset: 0x74 */ + __IO uint32_t GPB_MFPL; /* Offset: 0x78 */ + __IO uint32_t GPB_MFPH; /* Offset: 0x7C */ + __IO uint32_t GPC_MFPL; /* Offset: 0x80 */ + __IO uint32_t GPC_MFPH; /* Offset: 0x84 */ + __IO uint32_t GPD_MFPL; /* Offset: 0x88 */ + __IO uint32_t GPD_MFPH; /* Offset: 0x8C */ + __IO uint32_t GPE_MFPL; /* Offset: 0x90 */ + __IO uint32_t GPE_MFPH; /* Offset: 0x94 */ + __IO uint32_t GPF_MFPL; /* Offset: 0x98 */ + __IO uint32_t GPF_MFPH; /* Offset: 0x9c */ + __IO uint32_t GPG_MFPL; /* Offset: 0xA0 */ + __IO uint32_t GPG_MFPH; /* Offset: 0xA4 */ + __I uint32_t RESERVE4[18]; + __IO uint32_t DDR_DSCTL; /* Offset: 0xF0 */ + __I uint32_t RESERVE5[3]; + __IO uint32_t PORDISCR; /* Offset: 0x100 */ + __IO uint32_t ICEDBGCR; /* Offset: 0x104 */ + __IO uint32_t ERRADDCR; /* Offset: 0x108 */ + __I uint32_t RESERVE6[59]; + __IO uint32_t IRCTCTL; /* Offset: 0x1F8 */ + __IO uint32_t REGWPCTL; /* Offset: 0x1FC */ + + +} SYS_T; + + +/* SYS GPA_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPA_MFPH Bit Field Definitions */ +#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 */ + +/* SYS GPB_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPB_MFPH Bit Field Definitions */ +#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 */ + +/* SYS GPC_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPC_MFPH Bit Field Definitions */ +#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 */ + +/* SYS GPD_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPD_MFPH Bit Field Definitions */ +#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 */ + +/* SYS GPE_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPE_MFPH Bit Field Definitions */ +#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 */ + +/* SYS GPF_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPF_MFPH Bit Field Definitions */ +#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 */ + +/* SYS GPG_MFPL Bit Field Definitions */ +#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 */ + +/* SYS GPG_MFPH Bit Field Definitions */ +#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 */ + +/*@}*/ /* end of group NUC980_SYS_EXPORTED_CONSTANTS */ + + +/********************* Bit definition of GPA_MFPL register **********************/ +#define SYS_GPA_MFPL_PA0MFP_GPIO (0x00UL< +#include +#include +#include "nuc980.h" + + +/** @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 16ul /*!< UART2 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART3_FIFO_SIZE 16ul /*!< UART3 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART4_FIFO_SIZE 16ul /*!< UART3 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART5_FIFO_SIZE 16ul /*!< UART3 supports separated receive/transmit 16/16 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 */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART_LINCTL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_LINCTL_BRKFL(x) (((x)-1) << UART_LINCTL_BRKFL_Pos) /*!< UART_LINCTL setting to set LIN Break Field Length, x = 10 ~ 15, default value is 12 \hideinitializer */ +#define UART_LINCTL_BSL(x) (((x)-1) << UART_LINCTL_BSL_Pos) /*!< UART_LINCTL setting to set LIN Break/Sync Delimiter Length, x = 1 ~ 4 \hideinitializer */ +#define UART_LINCTL_HSEL_BREAK (0x0UL << UART_LINCTL_HSEL_Pos) /*!< UART_LINCTL setting to set LIN Header Select to break field \hideinitializer */ +#define UART_LINCTL_HSEL_BREAK_SYNC (0x1UL << UART_LINCTL_HSEL_Pos) /*!< UART_LINCTL setting to set LIN Header Select to break field and sync field \hideinitializer */ +#define UART_LINCTL_HSEL_BREAK_SYNC_ID (0x2UL << UART_LINCTL_HSEL_Pos) /*!< UART_LINCTL setting to set LIN Header Select to break field, sync field and ID field \hideinitializer */ +#define UART_LINCTL_PID(x) ((x) << UART_LINCTL_PID_Pos) /*!< UART_LINCTL setting to set LIN PID value \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 */ + +typedef struct +{ + uint32_t DAT; /*!< [0x0000] UART Receive/Transmit Buffer Register */ + uint32_t INTEN; /*!< [0x0004] UART Interrupt Enable Register */ + uint32_t FIFO; /*!< [0x0008] UART FIFO Control Register */ + uint32_t LINE; /*!< [0x000c] UART Line Control Register */ + uint32_t MODEM; /*!< [0x0010] UART Modem Control Register */ + uint32_t MODEMSTS; /*!< [0x0014] UART Modem Status Register */ + uint32_t FIFOSTS; /*!< [0x0018] UART FIFO Status Register */ + uint32_t INTSTS; /*!< [0x001c] UART Interrupt Status Register */ + uint32_t TOUT; /*!< [0x0020] UART Time-out Register */ + uint32_t BAUD; /*!< [0x0024] UART Baud Rate Divider Register */ + uint32_t IRDA; /*!< [0x0028] UART IrDA Control Register */ + uint32_t ALTCTL; /*!< [0x002c] UART Alternate Control/Status Register */ + uint32_t FUNCSEL; /*!< [0x0030] UART Function Select Register */ + uint32_t LINCTL; /*!< [0x0034] UART LIN Control Register */ + uint32_t LINSTS; /*!< [0x0038] UART LIN Status Register */ + uint32_t BRCOMP; /*!< [0x003c] UART Baud Rate Compensation Register */ + uint32_t WKCTL; /*!< [0x0040] UART Wake-up Control Register */ + uint32_t WKSTS; /*!< [0x0044] UART Wake-up Status Register */ + uint32_t DWKCOMP; /*!< [0x0048] UART Incoming Data Wake-up Compensation Register */ + +} UART_T; + +#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_LINIEN_Pos (8) /*!< UART_T::INTEN: LINIEN Position */ +#define UART_INTEN_LINIEN_Msk (0x1ul << UART_INTEN_LINIEN_Pos) /*!< UART_T::INTEN: LINIEN 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_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_LINIF_Pos (7) /*!< UART_T::INTSTS: LINIF Position */ +#define UART_INTSTS_LINIF_Msk (0x1ul << UART_INTSTS_LINIF_Pos) /*!< UART_T::INTSTS: LINIF 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_LININT_Pos (15) /*!< UART_T::INTSTS: LININT Position */ +#define UART_INTSTS_LININT_Msk (0x1ul << UART_INTSTS_LININT_Pos) /*!< UART_T::INTSTS: LININT 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_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 (0x3ul << 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_LINCTL_SLVEN_Pos (0) /*!< UART_T::LINCTL: SLVEN Position */ +#define UART_LINCTL_SLVEN_Msk (0x1ul << UART_LINCTL_SLVEN_Pos) /*!< UART_T::LINCTL: SLVEN Mask */ + +#define UART_LINCTL_SLVHDEN_Pos (1) /*!< UART_T::LINCTL: SLVHDEN Position */ +#define UART_LINCTL_SLVHDEN_Msk (0x1ul << UART_LINCTL_SLVHDEN_Pos) /*!< UART_T::LINCTL: SLVHDEN Mask */ + +#define UART_LINCTL_SLVAREN_Pos (2) /*!< UART_T::LINCTL: SLVAREN Position */ +#define UART_LINCTL_SLVAREN_Msk (0x1ul << UART_LINCTL_SLVAREN_Pos) /*!< UART_T::LINCTL: SLVAREN Mask */ + +#define UART_LINCTL_SLVDUEN_Pos (3) /*!< UART_T::LINCTL: SLVDUEN Position */ +#define UART_LINCTL_SLVDUEN_Msk (0x1ul << UART_LINCTL_SLVDUEN_Pos) /*!< UART_T::LINCTL: SLVDUEN Mask */ + +#define UART_LINCTL_MUTE_Pos (4) /*!< UART_T::LINCTL: MUTE Position */ +#define UART_LINCTL_MUTE_Msk (0x1ul << UART_LINCTL_MUTE_Pos) /*!< UART_T::LINCTL: MUTE Mask */ + +#define UART_LINCTL_SENDH_Pos (8) /*!< UART_T::LINCTL: SENDH Position */ +#define UART_LINCTL_SENDH_Msk (0x1ul << UART_LINCTL_SENDH_Pos) /*!< UART_T::LINCTL: SENDH Mask */ + +#define UART_LINCTL_IDPEN_Pos (9) /*!< UART_T::LINCTL: IDPEN Position */ +#define UART_LINCTL_IDPEN_Msk (0x1ul << UART_LINCTL_IDPEN_Pos) /*!< UART_T::LINCTL: IDPEN Mask */ + +#define UART_LINCTL_BRKDETEN_Pos (10) /*!< UART_T::LINCTL: BRKDETEN Position */ +#define UART_LINCTL_BRKDETEN_Msk (0x1ul << UART_LINCTL_BRKDETEN_Pos) /*!< UART_T::LINCTL: BRKDETEN Mask */ + +#define UART_LINCTL_LINRXOFF_Pos (11) /*!< UART_T::LINCTL: LINRXOFF Position */ +#define UART_LINCTL_LINRXOFF_Msk (0x1ul << UART_LINCTL_LINRXOFF_Pos) /*!< UART_T::LINCTL: LINRXOFF Mask */ + +#define UART_LINCTL_BITERREN_Pos (12) /*!< UART_T::LINCTL: BITERREN Position */ +#define UART_LINCTL_BITERREN_Msk (0x1ul << UART_LINCTL_BITERREN_Pos) /*!< UART_T::LINCTL: BITERREN Mask */ + +#define UART_LINCTL_BRKFL_Pos (16) /*!< UART_T::LINCTL: BRKFL Position */ +#define UART_LINCTL_BRKFL_Msk (0xful << UART_LINCTL_BRKFL_Pos) /*!< UART_T::LINCTL: BRKFL Mask */ + +#define UART_LINCTL_BSL_Pos (20) /*!< UART_T::LINCTL: BSL Position */ +#define UART_LINCTL_BSL_Msk (0x3ul << UART_LINCTL_BSL_Pos) /*!< UART_T::LINCTL: BSL Mask */ + +#define UART_LINCTL_HSEL_Pos (22) /*!< UART_T::LINCTL: HSEL Position */ +#define UART_LINCTL_HSEL_Msk (0x3ul << UART_LINCTL_HSEL_Pos) /*!< UART_T::LINCTL: HSEL Mask */ + +#define UART_LINCTL_PID_Pos (24) /*!< UART_T::LINCTL: PID Position */ +#define UART_LINCTL_PID_Msk (0xfful << UART_LINCTL_PID_Pos) /*!< UART_T::LINCTL: PID Mask */ + +#define UART_LINSTS_SLVHDETF_Pos (0) /*!< UART_T::LINSTS: SLVHDETF Position */ +#define UART_LINSTS_SLVHDETF_Msk (0x1ul << UART_LINSTS_SLVHDETF_Pos) /*!< UART_T::LINSTS: SLVHDETF Mask */ + +#define UART_LINSTS_SLVHEF_Pos (1) /*!< UART_T::LINSTS: SLVHEF Position */ +#define UART_LINSTS_SLVHEF_Msk (0x1ul << UART_LINSTS_SLVHEF_Pos) /*!< UART_T::LINSTS: SLVHEF Mask */ + +#define UART_LINSTS_SLVIDPEF_Pos (2) /*!< UART_T::LINSTS: SLVIDPEF Position */ +#define UART_LINSTS_SLVIDPEF_Msk (0x1ul << UART_LINSTS_SLVIDPEF_Pos) /*!< UART_T::LINSTS: SLVIDPEF Mask */ + +#define UART_LINSTS_SLVSYNCF_Pos (3) /*!< UART_T::LINSTS: SLVSYNCF Position */ +#define UART_LINSTS_SLVSYNCF_Msk (0x1ul << UART_LINSTS_SLVSYNCF_Pos) /*!< UART_T::LINSTS: SLVSYNCF Mask */ + +#define UART_LINSTS_BRKDETF_Pos (8) /*!< UART_T::LINSTS: BRKDETF Position */ +#define UART_LINSTS_BRKDETF_Msk (0x1ul << UART_LINSTS_BRKDETF_Pos) /*!< UART_T::LINSTS: BRKDETF Mask */ + +#define UART_LINSTS_BITEF_Pos (9) /*!< UART_T::LINSTS: BITEF Position */ +#define UART_LINSTS_BITEF_Msk (0x1ul << UART_LINSTS_BITEF_Pos) /*!< UART_T::LINSTS: BITEF 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 */ + + +#define UART0 ((UART_T *) UART0_BA) +#define UART1 ((UART_T *) UART1_BA) +#define UART2 ((UART_T *) UART2_BA) +#define UART3 ((UART_T *) UART3_BA) +#define UART4 ((UART_T *) UART4_BA) +#define UART5 ((UART_T *) UART5_BA) +#define UART6 ((UART_T *) UART6_BA) +#define UART7 ((UART_T *) UART7_BA) +#define UART8 ((UART_T *) UART8_BA) +#define UART9 ((UART_T *) UART9_BA) + + +/** @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 Enable specified UART interrupt + * + * @param[in] uart The pointer of the specified UART module + * @param[in] u32eIntSel Interrupt type select + * - \ref UART_INTEN_ABRIEN_Msk : Auto baud rate interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wakeup interrupt + * - \ref UART_INTEN_LINIEN_Msk : Lin bus 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_ABRIEN_Msk : Auto baud rate interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wakeup interrupt + * - \ref UART_INTEN_LINIEN_Msk : Lin bus 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_HWBUFEINT_Msk : In DMA Mode, Buffer Error Interrupt Indicator + * - \ref UART_INTSTS_HWTOINT_Msk : In DMA Mode, Time-out Interrupt Indicator + * - \ref UART_INTSTS_HWMODINT_Msk : In DMA Mode, MODEM Status Interrupt Indicator + * - \ref UART_INTSTS_HWRLSINT_Msk : In DMA Mode, Receive Line Status Interrupt Indicator + * - \ref UART_INTSTS_HWBUFEIF_Msk : In DMA Mode, Buffer Error Interrupt Flag + * - \ref UART_INTSTS_HWTOIF_Msk : In DMA Mode, Time-out Interrupt Flag + * - \ref UART_INTSTS_HWMODIF_Msk : In DMA Mode, MODEM Interrupt Flag + * - \ref UART_INTSTS_HWRLSIF_Msk : In DMA Mode, Receive Line Status Flag + * - \ref UART_INTSTS_LININT_Msk : LIN Bus 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_LINIF_Msk : LIN Bus 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. + * 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 */ +void UART_CLEAR_RTS(UART_T *uart); +void UART_SET_RTS(UART_T *uart); + +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_SetLineConfig(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); +void UART_SelectLINMode(UART_T *uart, uint32_t u32Mode, uint32_t u32BreakLength); +uint32_t UART_Write(UART_T *uart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes); + + + + +/*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group UART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + +#endif /*__NU_UART_H__*/ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_usbd.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_usbd.h new file mode 100644 index 0000000000..85c5c26ede --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_usbd.h @@ -0,0 +1,942 @@ +/**************************************************************************//** + * @file usbd.h + * @version V1.00 + * $Revision: 3 $ + * $Date: 18/08/05 10:19a $ + * @brief 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 Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USBD_Driver USBD Driver + @{ +*/ + +/** @addtogroup 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 | 0x100) /*!DMACTL = (USBD->DMACTL & ~(USBD_DMACTL_EPNUM_Msk | USBD_DMACTL_DMARD_Msk | 0x100)) | 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); /*!Introduction + * + * This user manual describes the usage of NUC980 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 __NUC980_H__ + #define __NUC980_H__ + + #include + + /** @addtogroup NUC980_PERIPHERAL_MEM_MAP Peripheral Memory Base + Memory Mapped Structure for NUC980 Peripheral + @{ + */ + + /*!< AHB peripherals */ + #define SYS_BA 0xB0000000 /* Global Control */ + #define CLK_BA 0xB0000200 /* Clock Control */ + #define SDIC_BA 0xB0002000 + #define EBI_BA 0xB0010000 /* EBI Control */ + #define GPIO_BA 0xB0004000 + #define PDMA0_BA 0xB0008000 + #define PDMA1_BA 0xB0009000 + #define EMC0_BA 0xB0012000 + #define EHCI_BA 0xB0015000 + #define USBD_BA 0xB0016000 + #define OHCI_BA 0xB0017000 + #define SDH_BA 0xB0018000 + #define FMI_BA 0xB0019000 + #define CRPT_BA 0xB001C000 + #define I2S_BA 0xB0020000 + #define EMC1_BA 0xB0022000 + #define CAP0_BA 0xB0024000 + #define CAP1_BA 0xB0014000 + + #define PA_BA 0xB0004000 + #define PB_BA 0xB0004040 + #define PC_BA 0xB0004080 + #define PD_BA 0xB00040C0 + #define PE_BA 0xB0004100 + #define PF_BA 0xB0004140 + #define PG_BA 0xB0004180 + + /*!< APB peripherals */ + + #define WDT_BA 0xB0040000 /* Watch Dog Timer */ + #define WWDT_BA 0xB0040100 /* Windows Watch Dog Timer */ + #define RTC_BA 0xB0041000 + #define AIC_BA 0xB0042000 /* Interrupt Controller */ + #define ADC_BA 0xB0043000 + #define ETMR0_BA 0xB0050000 /* ETimer0 */ + #define ETMR1_BA 0xB0050100 /* ETimer1 */ + #define ETMR2_BA 0xB0051000 /* ETimer2 */ + #define ETMR3_BA 0xB0051100 /* ETimer3 */ + #define ETMR4_BA 0xB0052000 /* ETimer4 */ + #define ETMR5_BA 0xB0052100 /* ETimer5 */ + #define PWM0_BA 0xB0058000 + #define PWM1_BA 0xB0059000 + #define QSPI0_BA 0xB0060000 + #define SPI0_BA 0xB0061000 + #define SPI1_BA 0xB0062000 + #define UART0_BA 0xB0070000 /* UART0 Control */ + #define UART1_BA 0xB0071000 /* UART1 Control */ + #define UART2_BA 0xB0072000 + #define UART3_BA 0xB0073000 + #define UART4_BA 0xB0074000 + #define UART5_BA 0xB0075000 + #define UART6_BA 0xB0076000 + #define UART7_BA 0xB0077000 + #define UART8_BA 0xB0078000 + #define UART9_BA 0xB0079000 + #define I2C0_BA 0xB0080000 + #define I2C1_BA 0xB0081000 + #define I2C2_BA 0xB0082000 + #define I2C3_BA 0xB0083000 + #define SC0_BA 0xB0090000 + #define SC1_BA 0xB0091000 + #define CAN0_BA 0xB00A0000 + #define CAN1_BA 0xB00A1000 + #define CAN2_BA 0xB00A2000 + #define CAN3_BA 0xB00A3000 + + /*@}*/ /* end of group NUC980_PERIPHERAL_MEM_MAP */ + + /******************************************************************************/ + /* Device Specific Peripheral registers structures */ + /******************************************************************************/ + /** @addtogroup REGISTER Control Register + NUC980 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_WKUPSER0 (SYS_BA+0x050) /*!< System Wakeup Source Enable Register0 */ + #define REG_SYS_WKUPSER1 (SYS_BA+0x054) /*!< System Wakeup Source Enable Register1 */ + #define REG_SYS_WKUPSSR0 (SYS_BA+0x058) /*!< System Wakeup Source Status Register0 */ + #define REG_SYS_WKUPSSR1 (SYS_BA+0x05C) /*!< System Wakeup Source Status Register1 */ + #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 */ + + /*---------------------- 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 */ + + + /*---------------------- 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 */ + + + + /*---------------------- 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 */ + + + /*---------------------- I2S Interface Controller -------------------------*/ + /** + @addtogroup I2S I2S Interface Controller(I2S) + Memory Mapped Structure for I2S Controller + @{ */ + + #define REG_I2S_CON (I2S_BA+0x00) /*!< Audio controller control register */ + #define REG_I2S_RESET (I2S_BA+0x04) /*!< Sub block reset control register */ + #define REG_I2S_RDESB (I2S_BA+0x08) /*!< DMA destination base address register for record */ + #define REG_I2S_RDES_LENGTH (I2S_BA+0x0C) /*!< DMA destination length register for record */ + #define REG_I2S_RDESC (I2S_BA+0x10) /*!< DMA destination current address for record */ + #define REG_I2S_PDESB (I2S_BA+0x14) /*!< DMA destination current address for play */ + #define REG_I2S_PDES_LENGTH (I2S_BA+0x18) /*!< DMA destination length register for play */ + #define REG_I2S_PDESC (I2S_BA+0x1C) /*!< DMA destination current address register for play */ + #define REG_I2S_RSR (I2S_BA+0x20) /*!< Record status register */ + #define REG_I2S_PSR (I2S_BA+0x24) /*!< Play status register */ + #define REG_I2S_I2SCON (I2S_BA+0x28) /*!< I2S control register */ + #define REG_I2S_COUNTER (I2S_BA+0x2C) /*!< DMA count down values */ + #define REG_I2S_PCMCON (I2S_BA+0x30) /*!< PCM interface control register */ + #define REG_I2S_PCMS1ST (I2S_BA+0x34) /*!< PCM interface slot1 start register */ + #define REG_I2S_PCMS2ST (I2S_BA+0x38) /*!< PCM interface slot2 start register */ + #define REG_I2S_RDESB2 (I2S_BA+0x40) /*!< DMA destination base address register for record right channel */ + #define REG_I2S_PDESB2 (I2S_BA+0x44) /*!< DMA destination base address register for play right channel */ + + /**@}*/ /* end of I2S 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 */ + + /*---------------------- Serial Peripheral Interface Controller -------------------------*/ + /** + @addtogroup SPI Serial Peripheral Interface Controller(SPI) + Memory Mapped Structure for SPI Controller + @{ */ + + #define REG_QSPI0_CTL (QSPI0_BA+0x00) /*!< Control Register Address */ + #define REG_QSPI0_CLKDIV (QSPI0_BA+0x04) /*!< Divider Register Address */ + #define REG_QSPI0_SSCTL (QSPI0_BA+0x08) /*!< Slave Select Register Address */ + #define REG_QSPI0_PDMACTL (QSPI0_BA+0x0C) /*!< PDMA Control Register Address */ + #define REG_QSPI0_FIFOCTL (QSPI0_BA+0x10) /*!< FIFO Control Register Address */ + #define REG_QSPI0_STATUS (QSPI0_BA+0x14) /*!< Status Register Address */ + #define REG_QSPI0_TX (QSPI0_BA+0x20) /*!< Data Transmit Register Address */ + #define REG_QSPI0_RX (QSPI0_BA+0x30) /*!< Data Receive Register Address */ + + #define REG_SPI0_CTL (SPI0_BA+0x00) /*!< Control Register Address */ + #define REG_SPI0_CLKDIV (SPI0_BA+0x04) /*!< Divider Register Address */ + #define REG_SPI0_SSCTL (SPI0_BA+0x08) /*!< Slave Select Register Address */ + #define REG_SPI0_PDMACTL (SPI0_BA+0x0C) /*!< PDMA Control Register Address */ + #define REG_SPI0_FIFOCTL (SPI0_BA+0x10) /*!< FIFO Control Register Address */ + #define REG_SPI0_STATUS (SPI0_BA+0x14) /*!< Status Register Address */ + #define REG_SPI0_TX (SPI0_BA+0x20) /*!< Data Transmit Register Address */ + #define REG_SPI0_RX (SPI0_BA+0x30) /*!< Data Receive Register Address */ + + #define REG_SPI1_CTL (SPI1_BA+0x00) /*!< Control Register Address */ + #define REG_SPI1_CLKDIV (SPI1_BA+0x04) /*!< Divider Register Address */ + #define REG_SPI1_SSCTL (SPI1_BA+0x08) /*!< Slave Select Register Address */ + #define REG_SPI1_PDMACTL (SPI1_BA+0x0C) /*!< PDMA Control Register Address */ + #define REG_SPI1_FIFOCTL (SPI1_BA+0x10) /*!< FIFO Control Register Address */ + #define REG_SPI1_STATUS (SPI1_BA+0x14) /*!< Status Register Address */ + #define REG_SPI1_TX (SPI1_BA+0x20) /*!< Data Transmit Register Address */ + #define REG_SPI1_RX (SPI1_BA+0x30) /*!< Data Receive Register Address */ + + /**@}*/ /* end of SPI 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 */ + + + /**@}*/ /* end of UART 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_ETMR0_ECTL (ETMR0_BA+0x20) /*!< Enhance Timer 0 Extended Control 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_ETMR1_ECTL (ETMR1_BA+0x20) /*!< Enhance Timer 1 Extended Control 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_ETMR2_ECTL (ETMR2_BA+0x20) /*!< Enhance Timer 2 Extended Control 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 */ + #define REG_ETMR3_ECTL (ETMR3_BA+0x20) /*!< Enhance Timer 3 Extended Control Register */ + + #define REG_ETMR4_CTL (ETMR4_BA+0x00) /*!< Enhance Timer 4 Control Register */ + #define REG_ETMR4_PRECNT (ETMR4_BA+0x04) /*!< Enhance Timer 4 Pre-Scale Counter Register */ + #define REG_ETMR4_CMPR (ETMR4_BA+0x08) /*!< Enhance Timer 4 Compare Register */ + #define REG_ETMR4_IER (ETMR4_BA+0x0C) /*!< Enhance Timer 4 Interrupt Enable Register */ + #define REG_ETMR4_ISR (ETMR4_BA+0x10) /*!< Enhance Timer 4 Interrupt Status Register */ + #define REG_ETMR4_DR (ETMR4_BA+0x14) /*!< Enhance Timer 4 Data Register */ + #define REG_ETMR4_TCAP (ETMR4_BA+0x18) /*!< Enhance Timer 4 Capture Data Register */ + #define REG_ETMR4_ECTL (ETMR4_BA+0x20) /*!< Enhance Timer 4 Extended Control Register */ + + #define REG_ETMR5_CTL (ETMR5_BA+0x00) /*!< Enhance Timer 5 Control Register */ + #define REG_ETMR5_PRECNT (ETMR5_BA+0x04) /*!< Enhance Timer 5 Pre-Scale Counter Register */ + #define REG_ETMR5_CMPR (ETMR5_BA+0x08) /*!< Enhance Timer 5 Compare Register */ + #define REG_ETMR5_IER (ETMR5_BA+0x0C) /*!< Enhance Timer 5 Interrupt Enable Register */ + #define REG_ETMR5_ISR (ETMR5_BA+0x10) /*!< Enhance Timer 5 Interrupt Status Register */ + #define REG_ETMR5_DR (ETMR5_BA+0x14) /*!< Enhance Timer 5 Data Register */ + #define REG_ETMR5_TCAP (ETMR5_BA+0x18) /*!< Enhance Timer 5 Capture Data Register */ + #define REG_ETMR5_ECTL (ETMR5_BA+0x20) /*!< Enhance Timer 5 Extended Control 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 */ + #define REG_WDT_RSTCNT (WDT_BA+0x08) /*!< WDT Reset Counter 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_ACTCTL (SC0_BA+0x4C) /*!< SC0 Activation Control Register */ + + #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_ACTCTL (SC1_BA+0x4C) /*!< SC1 Activation Control 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_SRCCTL0 (AIC_BA+0x00) /* Source control register 0 */ + #define REG_AIC_SRCCTL1 (AIC_BA+0x04) /* Source control register 1 */ + #define REG_AIC_SRCCTL2 (AIC_BA+0x08) /* Source control register 2 */ + #define REG_AIC_SRCCTL3 (AIC_BA+0x0C) /* Source control register 3 */ + #define REG_AIC_SRCCTL4 (AIC_BA+0x10) /* Source control register 4 */ + #define REG_AIC_SRCCTL5 (AIC_BA+0x14) /* Source control register 5 */ + #define REG_AIC_SRCCTL6 (AIC_BA+0x18) /* Source control register 6 */ + #define REG_AIC_SRCCTL7 (AIC_BA+0x1C) /* Source control register 7 */ + #define REG_AIC_SRCCTL8 (AIC_BA+0x20) /* Source control register 8 */ + #define REG_AIC_SRCCTL9 (AIC_BA+0x24) /* Source control register 9 */ + #define REG_AIC_SRCCTL10 (AIC_BA+0x28) /* Source control register 10 */ + #define REG_AIC_SRCCTL11 (AIC_BA+0x2C) /* Source control register 11 */ + #define REG_AIC_SRCCTL12 (AIC_BA+0x30) /* Source control register 12 */ + #define REG_AIC_SRCCTL13 (AIC_BA+0x34) /* Source control register 13 */ + #define REG_AIC_SRCCTL14 (AIC_BA+0x38) /* Source control register 14 */ + #define REG_AIC_SRCCTL15 (AIC_BA+0x3C) /* Source control register 15 */ + #define REG_AIC_RAWSTS0 (AIC_BA+0x100) /* Interrupt raw status register */ + #define REG_AIC_RAWSTS1 (AIC_BA+0x104) /* Interrupt raw status register (Hign) */ + #define REG_AIC_ACTSTS0 (AIC_BA+0x108) /* Interrupt active status register */ + #define REG_AIC_ACTSTS1 (AIC_BA+0x10C) /* Interrupt active status register (Hign) */ + #define REG_AIC_INTSTS0 (AIC_BA+0x110) /* Interrupt status register */ + #define REG_AIC_INTSTS1 (AIC_BA+0x114) /* Interrupt status register (High) */ + #define REG_AIC_IRQNUM (AIC_BA+0x120) /* Interrupt source number register */ + #define REG_AIC_FIQNUM (AIC_BA+0x124) /* Output interrupt status register */ + #define REG_AIC_INTMSK0 (AIC_BA+0x128) /* Interrupt mask register */ + #define REG_AIC_INTMSK1 (AIC_BA+0x12C) /* Interrupt mask register (High) */ + #define REG_AIC_INTEN0 (AIC_BA+0x130) /* Mask enable command register */ + #define REG_AIC_INTEN1 (AIC_BA+0x134) /* Mask enable command register (High) */ + #define REG_AIC_INTDIS0 (AIC_BA+0x138) /* Mask disable command register */ + #define REG_AIC_INTDIS1 (AIC_BA+0x13C) /* Mask disable command register (High) */ + #define REG_AIC_EOIS (AIC_BA+0x150) /* End of service command register */ + #define REG_AIC_EOFS (AIC_BA+0x154) /* End of service command register */ + + /**@}*/ /* end of AIC 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 */ + + + + /*---------------------- Pulse Width Modulation Controller -------------------------*/ + /** + @addtogroup PWM Pulse Width Modulation Controller(PWM) + Memory Mapped Structure for PWM Controller + @{ */ + + #define REG_PWM0_PPR (PWM0_BA+0x00) /*!< PWM Pre-scale Register 0 */ + #define REG_PWM0_CSR (PWM0_BA+0x04) /*!< PWM Clock Select Register */ + #define REG_PWM0_PCR (PWM0_BA+0x08) /*!< PWM Control Register */ + #define REG_PWM0_CNR0 (PWM0_BA+0x0C) /*!< PWM Counter Register 0 */ + #define REG_PWM0_CMR0 (PWM0_BA+0x10) /*!< PWM Comparator Register 0 */ + #define REG_PWM0_PDR0 (PWM0_BA+0x14) /*!< PWM Data Register 0 */ + #define REG_PWM0_CNR1 (PWM0_BA+0x18) /*!< PWM Counter Register 1 */ + #define REG_PWM0_CMR1 (PWM0_BA+0x1C) /*!< PWM Comparator Register 1 */ + #define REG_PWM0_PDR1 (PWM0_BA+0x20) /*!< PWM Data Register 1 */ + #define REG_PWM0_CNR2 (PWM0_BA+0x24) /*!< PWM Counter Register 2 */ + #define REG_PWM0_CMR2 (PWM0_BA+0x28) /*!< PWM Comparator Register 2 */ + #define REG_PWM0_PDR2 (PWM0_BA+0x2C) /*!< PWM Data Register 2 */ + #define REG_PWM0_CNR3 (PWM0_BA+0x30) /*!< PWM Counter Register 3 */ + #define REG_PWM0_CMR3 (PWM0_BA+0x34) /*!< PWM Comparator Register 3 */ + #define REG_PWM0_PDR3 (PWM0_BA+0x38) /*!< PWM Data Register 3 */ + #define REG_PWM0_PIER (PWM0_BA+0x3C) /*!< PWM Timer Interrupt Enable Register */ + #define REG_PWM0_PIIR (PWM0_BA+0x40) /*!< PWM Timer Interrupt Identification Register */ + + #define REG_PWM1_PPR (PWM1_BA+0x00) /*!< PWM Pre-scale Register 0 */ + #define REG_PWM1_CSR (PWM1_BA+0x04) /*!< PWM Clock Select Register */ + #define REG_PWM1_PCR (PWM1_BA+0x08) /*!< PWM Control Register */ + #define REG_PWM1_CNR0 (PWM1_BA+0x0C) /*!< PWM Counter Register 0 */ + #define REG_PWM1_CMR0 (PWM1_BA+0x10) /*!< PWM Comparator Register 0 */ + #define REG_PWM1_PDR0 (PWM1_BA+0x14) /*!< PWM Data Register 0 */ + #define REG_PWM1_CNR1 (PWM1_BA+0x18) /*!< PWM Counter Register 1 */ + #define REG_PWM1_CMR1 (PWM1_BA+0x1C) /*!< PWM Comparator Register 1 */ + #define REG_PWM1_PDR1 (PWM1_BA+0x20) /*!< PWM Data Register 1 */ + #define REG_PWM1_CNR2 (PWM1_BA+0x24) /*!< PWM Counter Register 2 */ + #define REG_PWM1_CMR2 (PWM1_BA+0x28) /*!< PWM Comparator Register 2 */ + #define REG_PWM1_PDR2 (PWM1_BA+0x2C) /*!< PWM Data Register 2 */ + #define REG_PWM1_CNR3 (PWM1_BA+0x30) /*!< PWM Counter Register 3 */ + #define REG_PWM1_CMR3 (PWM1_BA+0x34) /*!< PWM Comparator Register 3 */ + #define REG_PWM1_PDR3 (PWM1_BA+0x38) /*!< PWM Data Register 3 */ + #define REG_PWM1_PIER (PWM1_BA+0x3C) /*!< PWM Timer Interrupt Enable Register */ + #define REG_PWM1_PIIR (PWM1_BA+0x40) /*!< PWM Timer Interrupt Identification Register */ + + /**@}*/ /* end of PWM register group */ + + + /*------------------ Capture Sensor Interface Controller ---------------------*/ + /** + @addtogroup CAP Capture Engine(CAP) + Memory Mapped Structure for CAP Controller + @{ */ + + #define REG_CAP0_CTL (CAP0_BA+0x000) /*!< Image Capture Interface Control Register */ + #define REG_CAP0_PAR (CAP0_BA+0x004) /*!< Image Capture Interface Parameter Register */ + #define REG_CAP0_INT (CAP0_BA+0x008) /*!< Image Capture Interface Interrupt Registe */ + #define REG_CAP0_POSTERIZE (CAP0_BA+0x00C) /*!< YUV Component Posterizing Factor Register */ + #define REG_CAP0_MD (CAP0_BA+0x010) /*!< Motion Detection Register */ + #define REG_CAP0_MDADDR (CAP0_BA+0x014) /*!< Motion Detection Output Address Register */ + #define REG_CAP0_MDYADDR (CAP0_BA+0x018) /*!< Motion Detection Temp YOutput Address Register */ + #define REG_CAP0_SEPIA (CAP0_BA+0x01C) /*!< Sepia Effect Control Register */ + #define REG_CAP0_CWSP (CAP0_BA+0x020) /*!< Cropping Window Starting Address Register */ + #define REG_CAP0_CWS (CAP0_BA+0x024) /*!< Cropping Window Size Register */ + #define REG_CAP0_PKTSL (CAP0_BA+0x028) /*!< Packet Scaling Vertical/Horizontal Factor Register (LSB) */ + #define REG_CAP0_PLNSL (CAP0_BA+0x02C) /*!< Planar Scaling Vertical/Horizontal Factor Register (LSB) */ + #define REG_CAP0_FRCTL (CAP0_BA+0x030) /*!< Scaling Frame Rate Factor Register */ + #define REG_CAP0_STRIDE (CAP0_BA+0x034) /*!< Frame Output Pixel Stride Register */ + #define REG_CAP0_FIFOTH (CAP0_BA+0x03C) /*!< FIFO threshold Register */ + #define REG_CAP0_CMPADDR (CAP0_BA+0x040) /*!< Compare Packet Memory Base Address Register */ + #define REG_CAP0_PKTSM (CAP0_BA+0x048) /*!< Packet Scaling Vertical/Horizontal Factor Register (MSB) */ + #define REG_CAP0_PLNSM (CAP0_BA+0x04C) /*!< Planar Scaling Vertical/Horizontal Factor Register (MSB) */ + #define REG_CAP0_CURADDRP (CAP0_BA+0x050) /*!< Current Packet System Memory Address Register */ + #define REG_CAP0_CURADDRY (CAP0_BA+0x054) /*!< Current Planar Y System Memory Address Register */ + #define REG_CAP0_CURADDRU (CAP0_BA+0x058) /*!< Current Planar U System Memory Address Register */ + #define REG_CAP0_CURADDRV (CAP0_BA+0x05C) /*!< Current Planar V System Memory Address Register */ + #define REG_CAP0_PKTBA0 (CAP0_BA+0x060) /*!< System Memory Packet Base Address Register */ + #define REG_CAP0_PKTBA1 (CAP0_BA+0x064) /*!< System Memory Packet Base Address Register */ + #define REG_CAP0_YBA (CAP0_BA+0x080) /*!< System Memory Planar Y Base Address Register */ + #define REG_CAP0_UBA (CAP0_BA+0x084) /*!< System Memory Planar U Base Address Register */ + #define REG_CAP0_VBA (CAP0_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 */ + + + /*@}*/ /* end of group REGISTER */ + + + /** @addtogroup IO_ROUTINE I/O Routines + The Declaration of NUC980 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 IO_ROUTINE */ + + /******************************************************************************/ + /* Legacy Constants */ + /******************************************************************************/ + /** @addtogroup Legacy_Constants Legacy Constants + NUC980 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 */ + +#endif /* __NUC980_H__ */ + +/*@}*/ /* end of group Legacy_Constants */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver.uvprojx b/bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver.uvprojx new file mode 100644 index 0000000000..4c4d8b40ca --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver.uvprojx @@ -0,0 +1,495 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + libstddriver-nuc980 + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + AT91SAM9260 + Atmel + IRAM(0x200000-0x200FFF) IRAM2(0x300000-0x300FFF) IROM(0x100000-0x107FFF) CLOCK(18432000) CPUTYPE(ARM926EJ-S) + + "STARTUP\Atmel\SAM9260.s" ("Atmel AT91SAM9260 Startup Code") + UL2ARM(-UV2077N9E -O47 -S0 -C0 -N00("ARM926EJ-S Core") -D00(0792603F) -L00(4) -FO7 -FD300000 -FC1000 -FN1 -FF0AT91SAM9_DF_P1056_CS1 -FS020000000 -FL083BE00) + 4210 + AT91SAM9260.H + + + + + + + + + + + 0 + 0 + + + + Atmel\SAM9260\ + Atmel\SAM9260\ + + 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 + + + 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 + + + ..\Include;..\Library + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x20000000 + 0x20800000 + + + + + + + + + + + + + src + + + nu_can.c + 1 + ..\Source\nu_can.c + + + nu_cap.c + 1 + ..\Source\nu_cap.c + + + nu_crypto.c + 1 + ..\Source\nu_crypto.c + + + nu_ebi.c + 1 + ..\Source\nu_ebi.c + + + nu_emac.c + 1 + ..\Source\nu_emac.c + + + nu_etimer.c + 1 + ..\Source\nu_etimer.c + + + nu_gpio.c + 1 + ..\Source\nu_gpio.c + + + nu_i2c.c + 1 + ..\Source\nu_i2c.c + + + nu_i2s.c + 1 + ..\Source\nu_i2s.c + + + nu_pdma.c + 1 + ..\Source\nu_pdma.c + + + nu_qspi.c + 1 + ..\Source\nu_qspi.c + + + nu_rtc.c + 1 + ..\Source\nu_rtc.c + + + nu_scuart.c + 1 + ..\Source\nu_scuart.c + + + nu_sdh.c + 1 + ..\Source\nu_sdh.c + + + nu_spi.c + 1 + ..\Source\nu_spi.c + + + nu_sys.c + 1 + ..\Source\nu_sys.c + + + nu_uart.c + 1 + ..\Source\nu_uart.c + + + nu_usbd.c + 1 + ..\Source\nu_usbd.c + + + nu_wdt.c + 1 + ..\Source\nu_wdt.c + + + nu_wwdt.c + 1 + ..\Source\nu_wwdt.c + + + + + + + + + + + + + +
diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver_4.uvproj b/bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver_4.uvproj new file mode 100644 index 0000000000..b5e013f72a --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Library/libStdDriver_4.uvproj @@ -0,0 +1,501 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + libStdDriver_4 + 0x4 + ARM-ADS + + + Nuvoton_ARM9_Series + Nuvoton + + + + + 0 + + + + + + + + + + + + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil4\ + libstddriver_keil4 + 0 + 1 + 1 + 1 + 1 + .\build\keil4\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 1 + 0 + xcopy /y ".\build\keil4\@L.lib" "." + + 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 + 0 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + + 0 + -1 + + + + + + + + + + + + + + + + + + + 1 + 0 + 0 + 1 + 1 + 4101 + + 0 + NULink\Nu_Link.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 + 0x20000000 + 0x28000 + + + 1 + 0x0 + 0x80000 + + + 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 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + --c99 + + + ..\Library;..\Include + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x20000000 + + + + + + + + + + + + src + + + nu_can.c + 1 + ..\Source\nu_can.c + + + nu_cap.c + 1 + ..\Source\nu_cap.c + + + nu_crypto.c + 1 + ..\Source\nu_crypto.c + + + nu_ebi.c + 1 + ..\Source\nu_ebi.c + + + nu_emac.c + 1 + ..\Source\nu_emac.c + + + nu_etimer.c + 1 + ..\Source\nu_etimer.c + + + nu_gpio.c + 1 + ..\Source\nu_gpio.c + + + nu_i2c.c + 1 + ..\Source\nu_i2c.c + + + nu_i2s.c + 1 + ..\Source\nu_i2s.c + + + nu_pdma.c + 1 + ..\Source\nu_pdma.c + + + nu_qspi.c + 1 + ..\Source\nu_qspi.c + + + nu_rtc.c + 1 + ..\Source\nu_rtc.c + + + nu_scuart.c + 1 + ..\Source\nu_scuart.c + + + nu_sdh.c + 1 + ..\Source\nu_sdh.c + + + nu_spi.c + 1 + ..\Source\nu_spi.c + + + nu_sys.c + 1 + ..\Source\nu_sys.c + + + nu_uart.c + 1 + ..\Source\nu_uart.c + + + nu_usbd.c + 1 + ..\Source\nu_usbd.c + + + nu_wdt.c + 1 + ..\Source\nu_wdt.c + + + nu_wwdt.c + 1 + ..\Source\nu_wwdt.c + + + + + + + +
diff --git a/bsp/nuvoton/libraries/nuc980/Driver/SConscript b/bsp/nuvoton/libraries/nuc980/Driver/SConscript new file mode 100644 index 0000000000..e3ac575c7c --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/SConscript @@ -0,0 +1,26 @@ +# RT-Thread building script for component +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +libs = [] +src = Glob('Source/*.c') + Glob('Source/*.cpp') +cpppath = [cwd + '/Include'] +libpath = [cwd + '/Library'] + +if not GetDepend('BSP_USE_STDDRIVER_SOURCE'): + if rtconfig.CROSS_TOOL == 'keil': + if GetOption('target') == 'mdk4' and os.path.isfile('./Library/libstddriver_keil4.lib'): + libs += ['libstddriver_keil4'] + if GetOption('target') == 'mdk5' and os.path.isfile('./Library/libstddriver_keil.lib'): + libs += ['libstddriver_keil'] + elif rtconfig.CROSS_TOOL == 'gcc' and os.path.isfile('./Library/libstddriver_gcc.a'): + libs += ['libstddriver_gcc'] + +if not libs: + group = DefineGroup('nuc980_driver', src, depend = [''], CPPPATH = cpppath) +else: + src = [] + group = DefineGroup('nuc980_driver', src, depend = [''], CPPPATH = cpppath, LIBS = libs, LIBPATH = libpath) + +Return('group') diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_can.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_can.c new file mode 100644 index 0000000000..ef93e202fb --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_can.c @@ -0,0 +1,1286 @@ +/**************************************************************************//** + * @file can.c + * @version V2.00 + * @brief NUC980 series CAN driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nu_can.h" +#include "nu_sys.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CAN_Driver CAN Driver + @{ +*/ + +/** @addtogroup CAN_EXPORTED_FUNCTIONS CAN Exported Functions + @{ +*/ + +/** @cond HIDDEN_SYMBOLS */ + +static uint8_t gu8LockCanIf[4ul][2ul] = {0ul}; /* The chip have 4 CANs. */ + +#define RETRY_COUNTS (0x10000000ul) + +#define TSEG1_MIN 2ul +#define TSEG1_MAX 16ul +#define TSEG2_MIN 1ul +#define TSEG2_MAX 8ul +#define BRP_MIN 1ul +#define BRP_MAX 1024ul /* 6-bit BRP field + 4-bit BRPE field*/ +#define SJW_MAX 4ul +#define BRP_INC 1ul + +/* #define DEBUG_PRINTF printf */ +#define DEBUG_PRINTF(...) + +static uint32_t CAN_Clock = 75000000ul; + +static uint32_t LockIF(CAN_T *tCAN); +static uint32_t LockIF_TL(CAN_T *tCAN); +static void ReleaseIF(CAN_T *tCAN, uint32_t u32IfNo); +static int can_update_spt(int sampl_pt, int tseg, int *tseg1, int *tseg2); + +/** + * @brief Check if any interface is available 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 a interface is + * available, set a flag to lock the interface. + */ +static uint32_t LockIF(CAN_T *tCAN) +{ + uint32_t u32CanNo; + uint32_t u32FreeIfNo = 2ul; + uint32_t u32IntMask; + + 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 u32FreeIfNo; + + /* 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); + + /* 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_PCLK2) * 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/nuc980/Driver/Source/nu_cap.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_cap.c new file mode 100644 index 0000000000..9c2f850dd2 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_cap.c @@ -0,0 +1,397 @@ +/**************************************************************************//** + * @file cap.c + * @brief CAP driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include "nuc980.h" +#include "nu_cap.h" +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CAP_Driver CAP Driver + @{ +*/ + + +/** @addtogroup CAP_EXPORTED_FUNCTIONS CAP Exported Functions + @{ +*/ + +/** + * @brief Open engine clock and sensor clock + * + * @param[in] VCAP The pointer of the specified CAP module + * + * @param[in] u32InFormat The bits corresponding VSP, HSP, PCLK, INFMT, SNRTYPE, OUTFMT, PDORD and PNFMT configurations. + * - VSP should be ether \ref CAP_PAR_VSP_LOW or \ref CAP_PAR_VSP_HIGH + * - HSP should be ether \ref CAP_PAR_HSP_LOW or \ref CAP_PAR_HSP_HIGH + * - PCLK should be ether \ref CAP_PAR_PCLKP_LOW or \ref CAP_PAR_PCLKP_HIGH + * - INFMT should be ether \ref CAP_PAR_INFMT_YUV422 or \ref CAP_PAR_INFMT_RGB565 + * - SNRTYPE should be ether \ref CAP_PAR_SENTYPE_CCIR601 or \ref CAP_PAR_SENTYPE_CCIR656 + * - OUTFMT should be one of the following setting + * - \ref CAP_PAR_OUTFMT_YUV422 + * - \ref CAP_PAR_OUTFMT_ONLY_Y + * - \ref CAP_PAR_OUTFMT_RGB555 + * - \ref CAP_PAR_OUTFMT_RGB565 + * - PDORD should be one of the following setting + * - \ref CAP_PAR_INDATORD_YUYV + * - \ref CAP_PAR_INDATORD_YVYU + * - \ref CAP_PAR_INDATORD_UYVY + * - \ref CAP_PAR_INDATORD_VYUY + * - \ref CAP_PAR_INDATORD_RGGB + * - \ref CAP_PAR_INDATORD_BGGR + * - \ref CAP_PAR_INDATORD_GBRG + * - \ref CAP_PAR_INDATORD_GRBG + * - PNFMT should be one of the following setting + * - \ref CAP_PAR_PLNFMT_YUV422 + * - \ref CAP_PAR_PLNFMT_YUV420 + * + * @param[in] u32OutFormet Capture output format, should be one of following setting + * - \ref CAP_CTL_PKTEN + * - \ref CAP_CTL_PLNEN + * + * @return None + * + * @details Initialize the Image Capture Interface. Register a call back for driver internal using + */ +void CAP_Open(CAP_T *VCAP, uint32_t u32InFormat, uint32_t u32OutFormet) +{ + VCAP->PAR = (VCAP->PAR & ~0x000007BF) | u32InFormat; + VCAP->CTL = (VCAP->CTL & ~0x00000060) | u32OutFormet; +} + +/** + * @brief Set Cropping Window Starting Address and Size + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32VStart: Cropping Window Vertical Starting Address. It should be 0 ~ 0x7FF. + * + * @param[in] u32HStart: Cropping Window Horizontal Starting Address. It should be 0 ~ 0x7FF. + * + * @param[in] u32Height: Cropping Window Height . It should be 0 ~ 0x7FF. + * + * @param[in] u32Width: Cropping Window Width. It should be 0 ~ 0x7FF. + * + * @return None + * + * @details Set Cropping Window Starting Address Register + */ +void CAP_SetCroppingWindow(CAP_T *VCAP, uint32_t u32VStart, uint32_t u32HStart, uint32_t u32Height, uint32_t u32Width) +{ + VCAP->CWSP = (VCAP->CWSP & ~(CAP_CWSP_CWSADDRV_Msk | CAP_CWSP_CWSADDRH_Msk)) + | (((u32VStart << 16) | u32HStart)); + + VCAP->CWS = (VCAP->CWS & ~(CAP_CWS_CWH_Msk | CAP_CWS_CWW_Msk)) + | ((u32Height << 16) | u32Width); +} + + +/** + * @brief Set System Memory Packet Base Address0 Register + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32Address : set PKTBA0 register, It should be 0x0 ~ 0xFFFFFFFF + * + * @return None + * + * @details Set System Memory Packet Base Address Register + */ +void CAP_SetPacketBuf(CAP_T *VCAP, uint32_t u32Address) +{ + VCAP->PKTBA0 = u32Address; + VCAP->CTL |= CAP_CTL_UPDATE_Msk; +} + +/** + * @brief Set System Memory Planar Y, U and V Base Address Registers. + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32YAddr : set YBA register, It should be 0x0 ~ 0xFFFFFFFF + * + * @param[in] u32UAddr : set UBA register, It should be 0x0 ~ 0xFFFFFFFF + * + * @param[in] u32VAddr : set VBA register, It should be 0x0 ~ 0xFFFFFFFF + * + * @return None + * + * @details Set System Memory Planar Y,U and V Base Address Registers + */ +void CAP_SetPlanarBuf(CAP_T *VCAP, uint32_t u32YAddr, uint32_t u32UAddr, uint32_t u32VAddr) +{ + VCAP->YBA = u32YAddr; + VCAP->UBA = u32UAddr; + VCAP->VBA = u32VAddr; + VCAP->CTL |= CAP_CTL_UPDATE_Msk; +} + + +/** + * @brief Close Image Capture Interface + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @return None + */ +void CAP_Close(CAP_T *VCAP) +{ + VCAP->CTL &= ~CAP_CTL_CAPEN; +} + + +/** + * @brief Set CAP Interrupt + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32IntMask Interrupt settings. It could be + * - \ref CAP_INT_VIEN_Msk + * - \ref CAP_INT_MEIEN_Msk + * - \ref CAP_INT_ADDRMIEN_Msk + * - \ref CAP_INT_MDIEN_Msk + * @return None + * + * @details Set Video Frame End Interrupt Enable, + * System Memory Error Interrupt Enable, + * Address Match Interrupt Enable, + * Motion Detection Output Finish Interrupt Enable. + */ +void CAP_EnableInt(CAP_T *VCAP, uint32_t u32IntMask) +{ + VCAP->INT = (VCAP->INT & ~(CAP_INT_VIEN_Msk | CAP_INT_MEIEN_Msk | CAP_INT_ADDRMIEN_Msk | CAP_INT_MDIEN_Msk)) + | u32IntMask; +} + +/** + * @brief Disable CAP Interrupt + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32IntMask Interrupt settings. It could be + * - \ref CAP_INT_VINTF_Msk + * - \ref CAP_INT_MEINTF_Msk + * - \ref CAP_INT_ADDRMINTF_Msk + * - \ref CAP_INT_MDINTF_Msk + * @return None + * + * @details Disable Video Frame End Interrupt , + * System Memory Error Interrupt , + * Address Match Interrupt and + * Motion Detection Output Finish Interrupt . + */ +void CAP_DisableInt(CAP_T *VCAP, uint32_t u32IntMask) +{ + VCAP->INT = (VCAP->INT & ~(u32IntMask)) ; +} + +/** + * @brief Start Image Capture Interface + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @return None + */ +void CAP_Start(CAP_T *VCAP) +{ + VCAP->CTL |= CAP_CTL_CAPEN; +} + +/** + * @brief Stop Image Capture Interface + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32FrameComplete : + * TRUE: Capture module automatically disable the CAP module after a frame had been captured + * FALSE: Stop Capture module now + * @return None + * + * @details if u32FrameComplete is set to TRUE then get a new frame and disable CAP module + */ +void CAP_Stop(CAP_T *VCAP, uint32_t u32FrameComplete) +{ + if (u32FrameComplete == FALSE) + VCAP->CTL &= ~CAP_CTL_CAPEN; + else + { + VCAP->CTL |= CAP_CTL_SHUTTER_Msk; + while (CAP_IS_STOPPED(VCAP)); + } +} + +/** + * @brief Set Packet Scaling Vertical and Horizontal Factor Register + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32VNumerator: Packet Scaling Vertical Factor N. It should be 0 ~ FFFF. + * + * @param[in] u32VDenominator: Packet Scaling Vertical Factor M. It should be 0 ~ FFFF. + * + * @param[in] u32HNumerator: Packet Scaling Vertical Factor N. It should be 0 ~ FFFF. + * + * @param[in] u32HDenominator: Packet Scaling Vertical Factor M. It should be 0 ~ FFFF. + * + * @return None + * + */ +void CAP_SetPacketScaling(CAP_T *VCAP, uint32_t u32VNumerator, uint32_t u32VDenominator, uint32_t u32HNumerator, uint32_t u32HDenominator) +{ + uint32_t u32NumeratorL, u32NumeratorH; + uint32_t u32DenominatorL, u32DenominatorH; + + u32NumeratorL = u32VNumerator & 0xFF; + u32NumeratorH = u32VNumerator >> 8; + u32DenominatorL = u32VDenominator & 0xFF; + u32DenominatorH = u32VDenominator >> 8; + VCAP->PKTSL = (VCAP->PKTSL & ~(CAP_PKTSL_PKTSVNL_Msk | CAP_PKTSL_PKTSVML_Msk)) + | ((u32NumeratorL << 24) | (u32DenominatorL << 16)); + VCAP->PKTSM = (VCAP->PKTSM & ~(CAP_PKTSM_PKTSVNH_Msk | CAP_PKTSM_PKTSVMH_Msk)) + | ((u32NumeratorH << 24) | (u32DenominatorH << 16)); + + u32NumeratorL = u32HNumerator & 0xFF; + u32NumeratorH = u32HNumerator >> 8; + u32DenominatorL = u32HDenominator & 0xFF; + u32DenominatorH = u32HDenominator >> 8; + VCAP->PKTSL = (VCAP->PKTSL & ~(CAP_PKTSL_PKTSHNL_Msk | CAP_PKTSL_PKTSHML_Msk)) + | ((u32NumeratorL << 8) | u32DenominatorL); + VCAP->PKTSM = (VCAP->PKTSM & ~(CAP_PKTSM_PKTSHNH_Msk | CAP_PKTSM_PKTSHMH_Msk)) + | ((u32NumeratorH << 8) | u32DenominatorH); +} + +/** + * @brief Set Planar Scaling Vertical and Horizontal Factor Register + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32VNumerator: Planar Scaling Vertical Factor N. It should be 0 ~ FFFF. + * + * @param[in] u32VDenominator: Planar Scaling Vertical Factor M. It should be 0 ~ FFFF. + * + * @param[in] u32HNumerator: Planar Scaling Vertical Factor N. It should be 0 ~ FFFF. + * + * @param[in] u32HDenominator: Planar Scaling Vertical Factor M. It should be 0 ~ FFFF. + * + * @return None + * + */ +void CAP_SetPlanarScaling(CAP_T *VCAP, uint32_t u32VNumerator, uint32_t u32VDenominator, uint32_t u32HNumerator, uint32_t u32HDenominator) +{ + uint32_t u32NumeratorL, u32NumeratorH; + uint32_t u32DenominatorL, u32DenominatorH; + + u32NumeratorL = u32VNumerator & 0xFF; + u32NumeratorH = u32VNumerator >> 8; + u32DenominatorL = u32VDenominator & 0xFF; + u32DenominatorH = u32VDenominator >> 8; + VCAP->PLNSL = (VCAP->PLNSL & ~(CAP_PLNSL_PLNSVNL_Msk | CAP_PLNSL_PLNSVML_Msk)) + | ((u32NumeratorL << 24) | (u32DenominatorL << 16)); + VCAP->PLNSM = (VCAP->PLNSM & ~(CAP_PLNSM_PLNSVNH_Msk | CAP_PLNSM_PLNSVMH_Msk)) + | ((u32NumeratorH << 24) | (u32DenominatorH << 16)); + + u32NumeratorL = u32HNumerator & 0xFF; + u32NumeratorH = u32HNumerator >> 8; + u32DenominatorL = u32HDenominator & 0xFF; + u32DenominatorH = u32HDenominator >> 8; + VCAP->PLNSL = (VCAP->PLNSL & ~(CAP_PLNSL_PLNSHNL_Msk | CAP_PLNSL_PLNSHML_Msk)) + | ((u32NumeratorL << 8) | u32DenominatorL); + VCAP->PLNSM = (VCAP->PLNSM & ~(CAP_PLNSM_PLNSHNH_Msk | CAP_PLNSM_PLNSHMH_Msk)) + | ((u32NumeratorH << 8) | u32DenominatorH); +} + +/** + * @brief Set Packet Frame Output Pixel Stride Width. + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32Stride : set PKTSTRIDE register, It should be 0x0 ~ 0x3FFF + * + * @return None + * + * @details Set Packet Frame Output Pixel Stride Width + */ +void CAP_SetPacketStride(CAP_T *VCAP, uint32_t u32Stride) +{ + VCAP->STRIDE = (VCAP->STRIDE & ~CAP_STRIDE_PKTSTRIDE_Msk) | u32Stride; +} + +/** + * @brief Set Planar Frame Output Pixel Stride Width. + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32Stride : set PLNSTRIDE register, It should be 0x0 ~ 0x3FFF + * + * @return None + * + * @details Set Planar Frame Output Pixel Stride Width + */ +void CAP_SetPlanarStride(CAP_T *VCAP, uint32_t u32Stride) +{ + VCAP->STRIDE = (VCAP->STRIDE & ~CAP_STRIDE_PLNSTRIDE_Msk) | u32Stride << CAP_STRIDE_PLNSTRIDE_Pos; +} + + +/** + * @brief Enable Motion Detection Function + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @param[in] u32Freq: Motion Detection Detect Frequency. It should be 0x0 ~ 0x3. + * + * @param[in] u32BlockSize: Motion Detection Block Size + * FALSE : 16x16 + * TRUE : 8x8 + * + * @param[in] u32Format: Motion Detection Save Mode + * FALSE : 1 bit DIFF + 7 Y Differential + * TRUE : 1 bit DIFF only + * + * @param[in] u32Threshold: Motion Detection Detect Threshold. It should be 0x0 ~ 0x1F. + * + * @param[in] u32YDetAddr : Motion Detection Detect Temp Y Output Address + * + * @param[in] u32DetAddr: Motion Detection Detect Address + * + * @return None + * + * @details Set Planar Frame Output Pixel Stride Width + */ +void CAP_EnableMotionDet(CAP_T *VCAP, uint32_t u32Freq, uint32_t u32BlockSize, uint32_t u32Format, uint32_t u32Threshold, uint32_t u32YDetAddr, uint32_t u32DetAddr) +{ + VCAP->MD = (VCAP->MD & ~(CAP_MD_MDSM_Msk | CAP_MD_MDBS_Msk | CAP_MD_MDEN_Msk)) | + ((CAP_MD_MDEN_Msk | (u32BlockSize ? CAP_MD_MDBS_Msk : 0)) | + (u32Format ? CAP_MD_MDSM_Msk : 0)); + + VCAP->MD = (VCAP->MD & ~CAP_MD_MDDF_Msk) | (u32Freq << CAP_MD_MDDF_Pos); + VCAP->MD = (VCAP->MD & ~CAP_MD_MDTHR_Msk) | (u32Threshold << CAP_MD_MDTHR_Pos); + + VCAP->MDYADDR = u32YDetAddr; + VCAP->MDADDR = u32DetAddr; +} + +/** + * @brief Enable Motion Detection Function + * + * @param[in] VCAP: The pointer of the specified CAP module + * + * @return None + * + * @details Set Planar Frame Output Pixel Stride Width + */ +void CAP_DisableMotionDet(CAP_T *VCAP) +{ + VCAP->MD &= ~CAP_MD_MDEN_Msk; +} + +/*@}*/ /* end of group CAP_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CAP_Driver */ + +/*@}*/ /* end of group Standard_Driver */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c new file mode 100644 index 0000000000..a9d44e3938 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c @@ -0,0 +1,2671 @@ +/**************************************************************************//** + * @file crypto.c + * @version V1.10 + * @brief Cryptographic Accelerator driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include "nuc980.h" +#include "nu_crypto.h" + +/** @cond HIDDEN_SYMBOLS */ + +#define ENABLE_DEBUG 0 + +#if ENABLE_DEBUG + #define CRPT_DBGMSG printf +#else + #define CRPT_DBGMSG(...) do { } while (0) /* disable debug */ +#endif + +/** @endcond HIDDEN_SYMBOLS */ + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CRYPTO_Driver CRYPTO Driver + @{ +*/ + + +/** @addtogroup CRYPTO_EXPORTED_FUNCTIONS CRYPTO Exported Functions + @{ +*/ + +/** @cond HIDDEN_SYMBOLS */ + +static uint32_t g_AES_CTL; + +static char hex_char_tbl[] = "0123456789abcdef"; + +static void dump_ecc_reg(char *str, uint32_t volatile regs[], int32_t count); +static char get_Nth_nibble_char(uint32_t val32, uint32_t idx); +static void Hex2Reg(char input[], uint32_t volatile reg[]); +static void Reg2Hex(int32_t count, uint32_t volatile reg[], char output[]); +static void Hex2RegEx(char input[], uint32_t volatile reg[], int shift); +static char ch2hex(char ch); +static int get_nibble_value(char c); + + +/** @endcond HIDDEN_SYMBOLS */ + +/** + * @brief Open PRNG function + * @param[in] crpt Reference to Crypto module. + * @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(CRPT_T *crpt, 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. + * @param[in] crpt Reference to Crypto module. + * @return None + */ +void PRNG_Start(CRPT_T *crpt) +{ + crpt->PRNG_CTL |= CRPT_PRNG_CTL_START_Msk; +} + +/** + * @brief Read the PRNG key. + * @param[in] crpt Reference to Crypto module. + * @param[out] u32RandKey The key buffer to store newly generated PRNG key. + * @return None + */ +void PRNG_Read(CRPT_T *crpt, 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] crpt Reference to Crypto module. + * @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(CRPT_T *crpt, uint32_t u32EncDec, + uint32_t u32OpMode, uint32_t u32KeySize, uint32_t u32SwapType) +{ + crpt->AES_CTL = (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 = crpt->AES_CTL; +} + +/** + * @brief Start AES encrypt/decrypt + * @param[in] crpt Reference to Crypto module. + * @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(CRPT_T *crpt, uint32_t u32DMAMode) +{ + crpt->AES_CTL = g_AES_CTL; + crpt->AES_CTL |= CRPT_AES_CTL_START_Msk | (u32DMAMode << CRPT_AES_CTL_DMALAST_Pos); +} + +/** + * @brief Set AES keys + * @param[in] crpt Reference to Crypto module. + * @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(CRPT_T *crpt, uint32_t au32Keys[], uint32_t u32KeySize) +{ + uint32_t i, wcnt, key_reg_addr; + + key_reg_addr = (uint32_t)&crpt->AES0_KEY[0]; + wcnt = 4UL + u32KeySize * 2UL; + + for (i = 0U; i < wcnt; i++) + { + outpw(key_reg_addr, au32Keys[i]); + key_reg_addr += 4UL; + } +} + +/** + * @brief Set AES initial vectors + * @param[in] crpt Reference to Crypto module. + * @param[in] au32IV A four entry word array contains AES initial vectors. + * @return None + */ +void AES_SetInitVect(CRPT_T *crpt, uint32_t au32IV[]) +{ + uint32_t i, key_reg_addr; + + key_reg_addr = (uint32_t)&crpt->AES0_IV[0]; + + for (i = 0U; i < 4U; i++) + { + outpw(key_reg_addr, au32IV[i]); + key_reg_addr += 4UL; + } +} + +/** + * @brief Set AES DMA transfer configuration. + * @param[in] crpt Reference to Crypto module. + * @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(CRPT_T *crpt, uint32_t u32SrcAddr, + uint32_t u32DstAddr, uint32_t u32TransCnt) +{ + uint32_t reg_addr; + + reg_addr = (uint32_t)&crpt->AES0_SADDR; + outpw(reg_addr, u32SrcAddr); + + reg_addr = (uint32_t)&crpt->AES0_DADDR; + outpw(reg_addr, u32DstAddr); + + reg_addr = (uint32_t)&crpt->AES0_CNT; + outpw(reg_addr, u32TransCnt); +} + + +/** + * @brief Open SHA encrypt function. + * @param[in] crpt Reference to Crypto module. + * @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 HMAC key byte count + * @return None + */ +void SHA_Open(CRPT_T *crpt, uint32_t u32OpMode, uint32_t u32SwapType, uint32_t hmac_key_len) +{ + crpt->HMAC_CTL = (u32OpMode << CRPT_HMAC_CTL_OPMODE_Pos) | + (u32SwapType << CRPT_HMAC_CTL_OUTSWAP_Pos); + + if (hmac_key_len != 0UL) + { + crpt->HMAC_KEYCNT = hmac_key_len; + crpt->HMAC_CTL |= CRPT_HMAC_CTL_HMACEN_Msk; + } +} + +/** + * @brief Start SHA encrypt + * @param[in] crpt Reference to Crypto module. + * @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(CRPT_T *crpt, uint32_t u32DMAMode) +{ + crpt->HMAC_CTL &= ~(0x7UL << 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] crpt Reference to Crypto module. + * @param[in] u32SrcAddr SHA DMA source address + * @param[in] u32TransCnt SHA DMA transfer byte count + * @return None + */ +void SHA_SetDMATransfer(CRPT_T *crpt, uint32_t u32SrcAddr, uint32_t u32TransCnt) +{ + crpt->HMAC_SADDR = u32SrcAddr; + crpt->HMAC_DMACNT = u32TransCnt; +} + +/** + * @brief Read the SHA digest. + * @param[in] crpt Reference to Crypto module. + * @param[out] u32Digest The SHA encrypt output digest. + * @return None + */ +void SHA_Read(CRPT_T *crpt, uint32_t u32Digest[]) +{ + uint32_t i, wcnt, reg_addr; + + 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; + } + + reg_addr = (uint32_t) & (crpt->HMAC_DGST[0]); + for (i = 0UL; i < wcnt; i++) + { + u32Digest[i] = inpw(reg_addr); + reg_addr += 4UL; + } +} + +/** @cond HIDDEN_SYMBOLS */ + +/*-----------------------------------------------------------------------------------------------*/ +/* */ +/* ECC */ +/* */ +/*-----------------------------------------------------------------------------------------------*/ + +#define ECCOP_POINT_MUL (0x0UL << CRPT_ECC_CTL_ECCOP_Pos) +#define ECCOP_MODULE (0x1UL << CRPT_ECC_CTL_ECCOP_Pos) +#define ECCOP_POINT_ADD (0x2UL << CRPT_ECC_CTL_ECCOP_Pos) +#define ECCOP_POINT_DOUBLE (0x0UL << CRPT_ECC_CTL_ECCOP_Pos) + +#define MODOP_DIV (0x0UL << CRPT_ECC_CTL_MODOP_Pos) +#define MODOP_MUL (0x1UL << CRPT_ECC_CTL_MODOP_Pos) +#define MODOP_ADD (0x2UL << CRPT_ECC_CTL_MODOP_Pos) +#define MODOP_SUB (0x3UL << CRPT_ECC_CTL_MODOP_Pos) + +enum +{ + CURVE_GF_P, + CURVE_GF_2M, +}; + +/*-----------------------------------------------------*/ +/* Define elliptic curve (EC): */ +/*-----------------------------------------------------*/ + +typedef struct e_curve_t +{ + E_ECC_CURVE curve_id; + int32_t Echar; + char Ea[144]; + char Eb[144]; + char Px[144]; + char Py[144]; + int32_t Epl; + char Pp[176]; + int32_t Eol; + char Eorder[176]; + int32_t key_len; + int32_t irreducible_k1; + int32_t irreducible_k2; + int32_t irreducible_k3; + int32_t GF; +} ECC_CURVE; + +const ECC_CURVE _Curve[] = +{ + { + /* NIST: Curve P-192 : y^2=x^3-ax+b (mod p) */ + CURVE_P_192, + 48, /* Echar */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* "000000000000000000000000000000000000000000000003" */ + "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", + "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", + "07192b95ffc8da78631011ed6b24cdd573f977a11e794811", + 58, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* "6277101735386680763835789423207666416083908700390324961279" */ + 58, /* Eol */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* "6277101735386680763835789423176059013767194773182842284081" */ + 192, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, + { + /* NIST: Curve P-224 : y^2=x^3-ax+b (mod p) */ + CURVE_P_224, + 56, /* Echar */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* "00000000000000000000000000000000000000000000000000000003" */ + "b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", + "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", + 70, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "0026959946667150639794667015087019630673557916260026308143510066298881" */ + 70, /* Eol */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* "0026959946667150639794667015087019625940457807714424391721682722368061" */ + 224, /* key_len */ + 9, + 8, + 3, + CURVE_GF_P + }, + { + /* NIST: Curve P-256 : y^2=x^3-ax+b (mod p) */ + CURVE_P_256, + 64, /* Echar */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* "0000000000000000000000000000000000000000000000000000000000000003" */ + "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + 78, /* Epl */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* "115792089210356248762697446949407573530086143415290314195533631308867097853951" */ + 78, /* Eol */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* "115792089210356248762697446949407573529996955224135760342422259061068512044369" */ + 256, /* key_len */ + 10, + 5, + 2, + CURVE_GF_P + }, + { + /* NIST: Curve P-384 : y^2=x^3-ax+b (mod p) */ + CURVE_P_384, + 96, /* Echar */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003" */ + "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", + "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", + "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", + 116, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* "39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319" */ + 116, /* Eol */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643" */ + 384, /* key_len */ + 12, + 3, + 2, + CURVE_GF_P + }, + { + /* NIST: Curve P-521 : y^2=x^3-ax+b (mod p)*/ + CURVE_P_521, + 131, /* Echar */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003" */ + "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + "0c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", + "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", + 157, /* Epl */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151" */ + 157, /* Eol */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* "6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449" */ + 521, /* key_len */ + 32, + 32, + 32, + CURVE_GF_P + }, + { + /* NIST: Curve B-163 : y^2+xy=x^3+ax^2+b */ + CURVE_B_163, + 41, /* Echar */ + "00000000000000000000000000000000000000001", + "20a601907b8c953ca1481eb10512f78744a3205fd", + "3f0eba16286a2d57ea0991168d4994637e8343e36", + "0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 49, /* Eol */ + "40000000000000000000292FE77E70C12A4234C33", /* "5846006549323611672814742442876390689256843201587" */ + 163, /* key_len */ + 7, + 6, + 3, + CURVE_GF_2M + }, + { + /* NIST: Curve B-233 : y^2+xy=x^3+ax^2+b */ + CURVE_B_233, + 59, /* Echar 59 */ + "00000000000000000000000000000000000000000000000000000000001", + "066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad", + "0fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b", + "1006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 70, /* Eol */ + "1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", /* "6901746346790563787434755862277025555839812737345013555379383634485463" */ + 233, /* key_len */ + 74, + 74, + 74, + CURVE_GF_2M + }, + { + /* NIST: Curve B-283 : y^2+xy=x^3+ax^2+b */ + CURVE_B_283, + 71, /* Echar */ + "00000000000000000000000000000000000000000000000000000000000000000000001", + "27b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5", + "5f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053", + "3676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 85, /* Eol */ + "3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", /* "7770675568902916283677847627294075626569625924376904889109196526770044277787378692871" */ + 283, /* key_len */ + 12, + 7, + 5, + CURVE_GF_2M + }, + { + /* NIST: Curve B-409 : y^2+xy=x^3+ax^2+b */ + CURVE_B_409, + 103, /* Echar */ + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f", + "15d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7", + "061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 123, /* Eol */ + "10000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", /* "661055968790248598951915308032771039828404682964281219284648798304157774827374805208143723762179110965979867288366567526771" */ + 409, /* key_len */ + 87, + 87, + 87, + CURVE_GF_2M + }, + { + /* NIST: Curve B-571 : y^2+xy=x^3+ax^2+b */ + CURVE_B_571, + 143, /* Echar */ + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "2f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a", + "303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19", + "37bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 172, /* Eol */ + "3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", /* "3864537523017258344695351890931987344298927329706434998657235251451519142289560424536143999389415773083133881121926944486246872462816813070234528288303332411393191105285703" */ + 571, /* key_len */ + 10, + 5, + 2, + CURVE_GF_2M + }, + { + /* NIST: Curve K-163 : y^2+xy=x^3+ax^2+b */ + CURVE_K_163, + 41, /* Echar */ + "00000000000000000000000000000000000000001", + "00000000000000000000000000000000000000001", + "2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8", + "289070fb05d38ff58321f2e800536d538ccdaa3d9", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 49, /* Eol */ + "4000000000000000000020108A2E0CC0D99F8A5EF", /* "5846006549323611672814741753598448348329118574063" */ + 163, /* key_len */ + 7, + 6, + 3, + CURVE_GF_2M + }, + { + /* NIST: Curve K-233 : y^2+xy=x^3+ax^2+b */ + CURVE_K_233, + 59, /* Echar 59 */ + "00000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000001", + "17232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126", + "1db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 70, /* Eol */ + "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", /* "3450873173395281893717377931138512760570940988862252126328087024741343" */ + 233, /* key_len */ + 74, + 74, + 74, + CURVE_GF_2M + }, + { + /* NIST: Curve K-283 : y^2+xy=x^3+ax^2+b */ + CURVE_K_283, + 71, /* Echar */ + "00000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000001", + "503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836", + "1ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 85, /* Eol */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", /* "3885337784451458141838923813647037813284811733793061324295874997529815829704422603873" */ + 283, /* key_len */ + 12, + 7, + 5, + CURVE_GF_2M + }, + { + /* NIST: Curve K-409 : y^2+xy=x^3+ax^2+b */ + CURVE_K_409, + 103, /* Echar */ + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746", + "1e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 123, /* Eol */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", /* "330527984395124299475957654016385519914202341482140609642324395022880711289249191050673258457777458014096366590617731358671" */ + 409, /* key_len */ + 87, + 87, + 87, + CURVE_GF_2M + }, + { + /* NIST: Curve K-571 : y^2+xy=x^3+ax^2+b */ + CURVE_K_571, + 143, /* Echar */ + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "26eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972", + "349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3", + 68, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* "26959946667150639794667015087019630673557916260026308143510066298881" */ + 172, /* Eol */ + "20000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", /* "1932268761508629172347675945465993672149463664853217499328617625725759571144780212268133978522706711834706712800825351461273674974066617311929682421617092503555733685276673" */ + 571, /* key_len */ + 10, + 5, + 2, + CURVE_GF_2M + }, + { + /* Koblitz: Curve secp192k1 : y2 = x3+ax+b over Fp */ + CURVE_KO_192, + 48, /* Echar */ + "00000000000000000000000000000000000000000", + "00000000000000000000000000000000000000003", + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + 58, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", /* p */ + 58, /* Eol */ + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", /* n */ + 192, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, + { + /* Koblitz: Curve secp224k1 : y2 = x3+ax+b over Fp */ + CURVE_KO_224, + 56, /* Echar */ + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000005", + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + 70, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* p */ + 70, /* Eol */ + "0000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", /* n */ + 224, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, + { + /* Koblitz: Curve secp256k1 : y2 = x3+ax+b over Fp */ + CURVE_KO_256, + 64, /* Echar */ + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000007", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + 78, /* Epl */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* p */ + 78, /* Eol */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", /* n */ + 256, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, + { + /* Brainpool: Curve brainpoolP256r1 */ + CURVE_BP_256, + 64, /* Echar */ + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* A */ + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* B */ + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* x */ + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* y */ + 78, /* Epl */ + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* p */ + 78, /* Eol */ + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* q */ + 256, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, + { + /* Brainpool: Curve brainpoolP384r1 */ + CURVE_BP_384, + 96, /* Echar */ + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", /* A */ + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", /* B */ + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* x */ + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* y */ + 116, /* Epl */ + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* p */ + 116, /* Eol */ + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* q */ + 384, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, + { + /* Brainpool: Curve brainpoolP512r1 */ + CURVE_BP_512, + 128, /* Echar */ + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", /* A */ + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", /* B */ + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* x */ + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* y */ + 156, /* Epl */ + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* p */ + 156, /* Eol */ + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* q */ + 512, /* key_len */ + 7, + 2, + 1, + CURVE_GF_P + }, +}; + +static ECC_CURVE *pCurve; +static ECC_CURVE Curve_Copy; + +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); + +static char temp_hex_str[160]; + + +#if ENABLE_DEBUG +static void dump_ecc_reg(char *str, uint32_t volatile regs[], int32_t count) +{ + int32_t i; + + printf("%s => ", str); + for (i = 0; i < count; i++) + { + printf("0x%08x ", regs[i]); + } + printf("\n"); +} +#else +static void dump_ecc_reg(char *str, uint32_t volatile regs[], int32_t count) +{ +} +#endif + +static char ch2hex(char ch) +{ + if (ch <= '9') + { + ch = ch - '0'; + } + else if ((ch <= 'z') && (ch >= 'a')) + { + ch = ch - 'a' + 10U; + } + else + { + ch = ch - 'A' + 10U; + } + return ch; +} + +static void Hex2Reg(char input[], uint32_t volatile reg[]) +{ + char hex; + int si, ri; + uint32_t i, val32; + + si = (int)strlen(input) - 1; + ri = 0; + + while (si >= 0) + { + val32 = 0UL; + for (i = 0UL; (i < 8UL) && (si >= 0); i++) + { + hex = ch2hex(input[si]); + val32 |= (uint32_t)hex << (i * 4UL); + si--; + } + reg[ri++] = val32; + } +} + +static void Hex2RegEx(char input[], uint32_t volatile reg[], int shift) +{ + uint32_t hex, carry; + int si, ri; + uint32_t i, val32; + + si = (int)strlen(input) - 1; + ri = 0L; + carry = 0UL; + while (si >= 0) + { + val32 = 0UL; + for (i = 0UL; (i < 8UL) && (si >= 0L); i++) + { + hex = (uint32_t)ch2hex(input[si]); + hex <<= shift; + + val32 |= (uint32_t)((hex & 0xFUL) | carry) << (i * 4UL); + carry = (hex >> 4UL) & 0xFUL; + si--; + } + reg[ri++] = val32; + } + if (carry != 0UL) + { + reg[ri] = carry; + } +} + +/** + * @brief Extract specified nibble from an unsigned word in character format. + * For example: + * Suppose val32 is 0x786543210, get_Nth_nibble_char(val32, 3) will return a '3'. + * @param[in] val32 The input unsigned word + * @param[in] idx The Nth nibble to be extracted. + * @return The nibble in character format. + */ +static char get_Nth_nibble_char(uint32_t val32, uint32_t idx) +{ + return hex_char_tbl[(val32 >> (idx * 4U)) & 0xfU ]; +} + + +static void Reg2Hex(int32_t count, uint32_t volatile reg[], char output[]) +{ + int32_t idx, ri; + uint32_t i; + + output[count] = 0U; + idx = count - 1; + + for (ri = 0; idx >= 0; ri++) + { + for (i = 0UL; (i < 8UL) && (idx >= 0); i++) + { + output[idx] = get_Nth_nibble_char(reg[ri], i); + idx--; + } + } +} + +static ECC_CURVE *get_curve(E_ECC_CURVE ecc_curve) +{ + uint32_t i; + ECC_CURVE *ret = NULL; + + for (i = 0UL; i < sizeof(_Curve) / sizeof(ECC_CURVE); i++) + { + if (ecc_curve == _Curve[i].curve_id) + { + memcpy((char *)&Curve_Copy, &_Curve[i], sizeof(ECC_CURVE)); + ret = &Curve_Copy; /* (ECC_CURVE *)&_Curve[i]; */ + } + if (ret != NULL) + { + break; + } + } + return ret; +} + +static int32_t ecc_init_curve(CRPT_T *crpt, E_ECC_CURVE ecc_curve) +{ + int32_t i, ret = 0; + + pCurve = get_curve(ecc_curve); + if (pCurve == NULL) + { + CRPT_DBGMSG("Cannot find curve %d!!\n", ecc_curve); + ret = -1; + } + + if (ret == 0) + { + for (i = 0; i < 18; i++) + { + crpt->ECC_A[i] = 0UL; + crpt->ECC_B[i] = 0UL; + crpt->ECC_X1[i] = 0UL; + crpt->ECC_Y1[i] = 0UL; + crpt->ECC_N[i] = 0UL; + } + + Hex2Reg(pCurve->Ea, crpt->ECC_A); + Hex2Reg(pCurve->Eb, crpt->ECC_B); + Hex2Reg(pCurve->Px, crpt->ECC_X1); + Hex2Reg(pCurve->Py, crpt->ECC_Y1); + + CRPT_DBGMSG("Key length = %d\n", pCurve->key_len); + dump_ecc_reg("CRPT_ECC_CURVE_A", crpt->ECC_A, 10); + dump_ecc_reg("CRPT_ECC_CURVE_B", crpt->ECC_B, 10); + dump_ecc_reg("CRPT_ECC_POINT_X1", crpt->ECC_X1, 10); + dump_ecc_reg("CRPT_ECC_POINT_Y1", crpt->ECC_Y1, 10); + + if (pCurve->GF == (int)CURVE_GF_2M) + { + crpt->ECC_N[0] = 0x1UL; + crpt->ECC_N[(pCurve->key_len) / 32] |= (1UL << ((pCurve->key_len) % 32)); + crpt->ECC_N[(pCurve->irreducible_k1) / 32] |= (1UL << ((pCurve->irreducible_k1) % 32)); + crpt->ECC_N[(pCurve->irreducible_k2) / 32] |= (1UL << ((pCurve->irreducible_k2) % 32)); + crpt->ECC_N[(pCurve->irreducible_k3) / 32] |= (1UL << ((pCurve->irreducible_k3) % 32)); + } + else + { + Hex2Reg(pCurve->Pp, crpt->ECC_N); + } + } + dump_ecc_reg("CRPT_ECC_CURVE_N", crpt->ECC_N, 10); + return ret; +} + +static int get_nibble_value(char c) +{ + if ((c >= '0') && (c <= '9')) + { + c = c - '0'; + } + + if ((c >= 'a') && (c <= 'f')) + { + c = c - 'a' + (char)10; + } + + if ((c >= 'A') && (c <= 'F')) + { + c = c - 'A' + (char)10; + } + return (int)c; +} + +static int ecc_strcmp(char *s1, char *s2) +{ + char c1, c2; + + while (*s1 == '0') s1++; + while (*s2 == '0') s2++; + + for (; *s1 || *s2; s1++, s2++) + { + if ((*s1 >= 'A') && (*s1 <= 'Z')) + c1 = *s1 + 32; + else + c1 = *s1; + + if ((*s2 >= 'A') && (*s2 <= 'Z')) + c2 = *s2 + 32; + else + c2 = *s2; + + if (c1 != c2) + return 1; + } + return 0; +} + +volatile uint32_t g_ECC_done, g_ECCERR_done; + +/** @endcond HIDDEN_SYMBOLS */ + +/** + * @brief ECC interrupt service routine. User application must invoke this function in + * his CRYPTO_IRQHandler() to let Crypto driver know ECC processing was done. + * @param[in] crpt Reference to Crypto module. + * @return none + */ +void ECC_Complete(CRPT_T *crpt) +{ + if (crpt->INTSTS & CRPT_INTSTS_ECCIF_Msk) + { + g_ECC_done = 1UL; + crpt->INTSTS = CRPT_INTSTS_ECCIF_Msk; + /* printf("ECC done IRQ.\n"); */ + } + + if (crpt->INTSTS & CRPT_INTSTS_ECCEIF_Msk) + { + g_ECCERR_done = 1UL; + crpt->INTSTS = CRPT_INTSTS_ECCEIF_Msk; + /* printf("ECCERRIF is set!!\n"); */ + } +} + +/** + * @brief Check if the private key is located in valid range of curve. + * @param[in] crpt Reference to Crypto module. + * @param[in] ecc_curve The pre-defined ECC curve. + * @param[in] private_k The input private key. + * @return 1 Is valid. + * @return 0 Is not valid. + * @return -1 Invalid curve. + */ +int ECC_IsPrivateKeyValid(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char private_k[]) +{ + uint32_t i; + int ret = -1; + + pCurve = get_curve(ecc_curve); + if (pCurve == NULL) + { + ret = -1; + } + + if (strlen(private_k) < strlen(pCurve->Eorder)) + { + ret = 1; + } + + if (strlen(private_k) > strlen(pCurve->Eorder)) + { + ret = 0; + } + + for (i = 0UL; i < strlen(private_k); i++) + { + if (get_nibble_value(private_k[i]) < get_nibble_value(pCurve->Eorder[i])) + { + ret = 1; + break; + } + if (get_nibble_value(private_k[i]) > get_nibble_value(pCurve->Eorder[i])) + { + ret = 0; + break; + } + } + return ret; +} + +/** + * @brief Given a private key and curve to generate the public key pair. + * @param[in] crpt Reference to Crypto module. + * @param[in] private_k The input private key. + * @param[in] ecc_curve The pre-defined ECC curve. + * @param[out] public_k1 The output public key 1. + * @param[out] public_k2 The output public key 2. + * @return 0 Success. + * @return -1 "ecc_curve" value is invalid. + */ +int32_t ECC_GeneratePublicKey(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *private_k, char public_k1[], char public_k2[]) +{ + int32_t i, ret = 0; + + if (ecc_init_curve(crpt, ecc_curve) != 0) + { + ret = -1; + } + + if (ret == 0) + { + for (i = 0; i < 18; i++) + { + crpt->ECC_K[i] = 0UL; + } + Hex2Reg(private_k, crpt->ECC_K); + + /* set FSEL (Field selection) */ + if (pCurve->GF == (int)CURVE_GF_2M) + { + crpt->ECC_CTL = 0UL; + } + else + { + /* CURVE_GF_P */ + crpt->ECC_CTL = CRPT_ECC_CTL_FSEL_Msk; + } + + g_ECC_done = g_ECCERR_done = 0UL; + crpt->ECC_CTL |= ((uint32_t)pCurve->key_len << CRPT_ECC_CTL_CURVEM_Pos) | + ECCOP_POINT_MUL | CRPT_ECC_CTL_START_Msk; + + while ((g_ECC_done | g_ECCERR_done) == 0UL) + { + } + + Reg2Hex(pCurve->Echar, crpt->ECC_X1, public_k1); + Reg2Hex(pCurve->Echar, crpt->ECC_Y1, public_k2); + } + + return ret; +} + +/** + * @brief Given a private key and curve to generate the public key pair. + * @param[in] crpt Reference to Crypto module. + * @param[out] x1 The x-coordinate of input point. + * @param[out] y1 The y-coordinate of input point. + * @param[in] k The private key + * @param[in] ecc_curve The pre-defined ECC curve. + * @param[out] x2 The x-coordinate of output point. + * @param[out] y2 The y-coordinate of output point. + * @return 0 Success. + * @return -1 "ecc_curve" value is invalid. + */ +int32_t ECC_Mutiply(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char x1[], char y1[], char *k, char x2[], char y2[]) +{ + int32_t i, ret = 0; + + if (ecc_init_curve(crpt, ecc_curve) != 0) + { + ret = -1; + } + + if (ret == 0) + { + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = 0UL; + crpt->ECC_Y1[i] = 0UL; + crpt->ECC_K[i] = 0UL; + } + Hex2Reg(x1, crpt->ECC_X1); + Hex2Reg(y1, crpt->ECC_Y1); + Hex2Reg(k, crpt->ECC_K); + + /* set FSEL (Field selection) */ + if (pCurve->GF == (int)CURVE_GF_2M) + { + crpt->ECC_CTL = 0UL; + } + else + { + /* CURVE_GF_P */ + crpt->ECC_CTL = CRPT_ECC_CTL_FSEL_Msk; + } + + g_ECC_done = g_ECCERR_done = 0UL; + crpt->ECC_CTL |= ((uint32_t)pCurve->key_len << CRPT_ECC_CTL_CURVEM_Pos) | + ECCOP_POINT_MUL | CRPT_ECC_CTL_START_Msk; + + while ((g_ECC_done | g_ECCERR_done) == 0UL) + { + } + + Reg2Hex(pCurve->Echar, crpt->ECC_X1, x2); + Reg2Hex(pCurve->Echar, crpt->ECC_Y1, y2); + } + + return ret; +} + +/** + * @brief Given a curve parameter, the other party's public key, and one's own private key to generate the secret Z. + * @param[in] crpt Reference to Crypto module. + * @param[in] ecc_curve The pre-defined ECC curve. + * @param[in] private_k One's own private key. + * @param[in] public_k1 The other party's publick key 1. + * @param[in] public_k2 The other party's publick key 2. + * @param[out] secret_z The ECC CDH secret Z. + * @return 0 Success. + * @return -1 "ecc_curve" value is invalid. + */ +int32_t ECC_GenerateSecretZ(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *private_k, char public_k1[], char public_k2[], char secret_z[]) +{ + int32_t i, ret = 0; + + if (ecc_init_curve(crpt, ecc_curve) != 0) + { + ret = -1; + } + + if (ret == 0) + { + for (i = 0; i < 18; i++) + { + crpt->ECC_K[i] = 0UL; + crpt->ECC_X1[i] = 0UL; + crpt->ECC_Y1[i] = 0UL; + } + + if ((ecc_curve == CURVE_B_163) || (ecc_curve == CURVE_B_233) || (ecc_curve == CURVE_B_283) || + (ecc_curve == CURVE_B_409) || (ecc_curve == CURVE_B_571) || (ecc_curve == CURVE_K_163)) + { + Hex2RegEx(private_k, crpt->ECC_K, 1); + } + else if ((ecc_curve == CURVE_K_233) || (ecc_curve == CURVE_K_283) || + (ecc_curve == CURVE_K_409) || (ecc_curve == CURVE_K_571)) + { + Hex2RegEx(private_k, crpt->ECC_K, 2); + } + else + { + Hex2Reg(private_k, crpt->ECC_K); + } + + Hex2Reg(public_k1, crpt->ECC_X1); + Hex2Reg(public_k2, crpt->ECC_Y1); + + /* set FSEL (Field selection) */ + if (pCurve->GF == (int)CURVE_GF_2M) + { + crpt->ECC_CTL = 0UL; + } + else + { + /* CURVE_GF_P */ + crpt->ECC_CTL = CRPT_ECC_CTL_FSEL_Msk; + } + g_ECC_done = g_ECCERR_done = 0UL; + crpt->ECC_CTL |= ((uint32_t)pCurve->key_len << CRPT_ECC_CTL_CURVEM_Pos) | + ECCOP_POINT_MUL | CRPT_ECC_CTL_START_Msk; + + while ((g_ECC_done | g_ECCERR_done) == 0UL) + { + } + + Reg2Hex(pCurve->Echar, crpt->ECC_X1, secret_z); + } + + return ret; +} + +/** @cond HIDDEN_SYMBOLS */ + +static void run_ecc_codec(CRPT_T *crpt, uint32_t mode) +{ + if ((mode & CRPT_ECC_CTL_ECCOP_Msk) == ECCOP_MODULE) + { + crpt->ECC_CTL = CRPT_ECC_CTL_FSEL_Msk; + } + else + { + if (pCurve->GF == (int)CURVE_GF_2M) + { + /* point */ + crpt->ECC_CTL = 0UL; + } + else + { + /* CURVE_GF_P */ + crpt->ECC_CTL = CRPT_ECC_CTL_FSEL_Msk; + } + } + + g_ECC_done = g_ECCERR_done = 0UL; + crpt->ECC_CTL |= ((uint32_t)pCurve->key_len << CRPT_ECC_CTL_CURVEM_Pos) | mode | CRPT_ECC_CTL_START_Msk; + while ((g_ECC_done | g_ECCERR_done) == 0UL) + { + } + + while (crpt->ECC_STS & CRPT_ECC_STS_BUSY_Msk) + { + } +} +/** @endcond HIDDEN_SYMBOLS */ + +/** + * @brief ECDSA digital signature generation. + * @param[in] crpt Reference to Crypto module. + * @param[in] ecc_curve The pre-defined ECC curve. + * @param[in] message The hash value of source context. + * @param[in] d The private key. + * @param[in] k The selected random integer. + * @param[out] R R of the (R,S) pair digital signature + * @param[out] S S of the (R,S) pair digital signature + * @return 0 Success. + * @return -1 "ecc_curve" value is invalid. + */ +int32_t ECC_GenerateSignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, + char *d, char *k, char *R, char *S) +{ + uint32_t volatile temp_result1[18], temp_result2[18]; + int32_t i, ret = 0; + + if (ecc_init_curve(crpt, ecc_curve) != 0) + { + ret = -1; + } + + if (ret == 0) + { + /* + * 1. Calculate e = HASH(m), where HASH is a cryptographic hashing algorithm, (i.e. SHA-1) + * (1) Use SHA to calculate e + */ + + /* 2. Select a random integer k form [1, n-1] + * (1) Notice that n is order, not prime modulus or irreducible polynomial function + */ + + /* + * 3. Compute r = x1 (mod n), where (x1, y1) = k * G. If r = 0, go to step 2 + * (1) Write the curve parameter A, B, and curve length M to corresponding registers + * (2) Write the prime modulus or irreducible polynomial function to N registers according + * (3) Write the point G(x, y) to X1, Y1 registers + * (4) Write the random integer k to K register + * (5) Set ECCOP(CRPT_ECC_CTL[10:9]) to 00 + * (6) Set FSEL(CRPT_ECC_CTL[8]) according to used curve of prime field or binary field + * (7) Set START(CRPT_ECC_CTL[0]) to 1 + * (8) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (9) Write the curve order and curve length to N ,M registers according + * (10) Write 0x0 to Y1 registers + * (11) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (12) Set MOPOP(CRPT_ECC_CTL[12:11]) to 10 + * (13) Set START(CRPT_ECC_CTL[0]) to 1 * + * (14) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (15) Read X1 registers to get r + */ + + /* 3-(4) Write the random integer k to K register */ + for (i = 0; i < 18; i++) + { + crpt->ECC_K[i] = 0UL; + } + Hex2Reg(k, crpt->ECC_K); + + run_ecc_codec(crpt, ECCOP_POINT_MUL); + + /* 3-(9) Write the curve order to N registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 3-(10) Write 0x0 to Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = 0UL; + } + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_ADD); + + /* 3-(15) Read X1 registers to get r */ + for (i = 0; i < 18; i++) + { + temp_result1[i] = crpt->ECC_X1[i]; + } + + Reg2Hex(pCurve->Echar, temp_result1, R); + + /* + * 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 + * (4) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (5) Set MOPOP(CRPT_ECC_CTL[12:11]) to 00 + * (6) Set START(CRPT_ECC_CTL[0]) to 1 + * (7) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (8) Read X1 registers to get k^-1 + * (9) Write the curve order and curve length to N ,M registers + * (10) Write r, d to X1, Y1 registers + * (11) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (12) Set MOPOP(CRPT_ECC_CTL[12:11]) to 01 + * (13) Set START(CRPT_ECC_CTL[0]) to 1 + * (14) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (15) Write the curve order to N registers + * (16) Write e to Y1 registers + * (17) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (18) Set MOPOP(CRPT_ECC_CTL[12:11]) to 10 + * (19) Set START(CRPT_ECC_CTL[0]) to 1 + * (20) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (21) Write the curve order and curve length to N ,M registers + * (22) Write k^-1 to Y1 registers + * (23) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (24) Set MOPOP(CRPT_ECC_CTL[12:11]) to 01 + * (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 s + */ + + /* S/W: GFp_add_mod_order(pCurve->key_len+2, 0, x1, a, R); */ + + /* 4-(1) Write the curve order to N registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 4-(2) Write 0x1 to Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = 0UL; + } + crpt->ECC_Y1[0] = 0x1UL; + + /* 4-(3) Write the random integer k to X1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = 0UL; + } + Hex2Reg(k, crpt->ECC_X1); + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_DIV); + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, crpt->ECC_X1, temp_hex_str); + CRPT_DBGMSG("(7) output = %s\n", temp_hex_str); +#endif + + /* 4-(8) Read X1 registers to get k^-1 */ + + for (i = 0; i < 18; i++) + { + temp_result2[i] = crpt->ECC_X1[i]; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, temp_result2, temp_hex_str); + CRPT_DBGMSG("k^-1 = %s\n", temp_hex_str); +#endif + + /* 4-(9) Write the curve order and curve length to N ,M registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 4-(10) Write r, d to X1, Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = temp_result1[i]; + } + + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = 0UL; + } + Hex2Reg(d, crpt->ECC_Y1); + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_MUL); + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, crpt->ECC_X1, temp_hex_str); + CRPT_DBGMSG("(14) output = %s\n", temp_hex_str); +#endif + + /* 4-(15) Write the curve order to N registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 4-(16) Write e to Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = 0UL; + } + Hex2Reg(message, crpt->ECC_Y1); + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_ADD); + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, crpt->ECC_X1, temp_hex_str); + CRPT_DBGMSG("(20) output = %s\n", temp_hex_str); +#endif + + /* 4-(21) Write the curve order and curve length to N ,M registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 4-(22) Write k^-1 to Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = temp_result2[i]; + } + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_MUL); + + /* 4-(27) Read X1 registers to get s */ + for (i = 0; i < 18; i++) + { + temp_result2[i] = crpt->ECC_X1[i]; + } + + Reg2Hex(pCurve->Echar, temp_result2, S); + + } /* ret == 0 */ + + return ret; +} + +/** + * @brief ECDSA dogotal signature verification. + * @param[in] crpt Reference to Crypto module. + * @param[in] ecc_curve The pre-defined ECC curve. + * @param[in] message The hash value of source context. + * @param[in] public_k1 The public key 1. + * @param[in] public_k2 The public key 2. + * @param[in] R R of the (R,S) pair digital signature + * @param[in] S S of the (R,S) pair digital signature + * @return 0 Success. + * @return -1 "ecc_curve" value is invalid. + * @return -2 Verification failed. + */ +int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, + char *public_k1, char *public_k2, char *R, char *S) +{ + uint32_t temp_result1[18], temp_result2[18]; + uint32_t temp_x[18], temp_y[18]; + int32_t i, ret = 0; + + /* + * 1. Verify that r and s are integers in the interval [1, n-1]. If not, the signature is invalid + * 2. Compute e = HASH (m), where HASH is the hashing algorithm in signature generation + * (1) Use SHA to calculate e + */ + + /* + * 3. Compute w = s^-1 (mod n) + * (1) Write the curve order to N registers + * (2) Write 0x1 to Y1 registers + * (3) Write s to X1 registers + * (4) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (5) Set MOPOP(CRPT_ECC_CTL[12:11]) to 00 + * (6) Set FSEL(CRPT_ECC_CTL[8]) according to used curve of prime field or binary field + * (7) Set START(CRPT_ECC_CTL[0]) to 1 + * (8) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (9) Read X1 registers to get w + */ + + if (ecc_init_curve(crpt, ecc_curve) != 0) + { + ret = -1; + } + + if (ret == 0) + { + /* 3-(1) Write the curve order to N registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 3-(2) Write 0x1 to Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = 0UL; + } + crpt->ECC_Y1[0] = 0x1UL; + + /* 3-(3) Write s to X1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = 0UL; + } + Hex2Reg(S, crpt->ECC_X1); + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_DIV); + + /* 3-(9) Read X1 registers to get w */ + for (i = 0; i < 18; i++) + { + temp_result2[i] = crpt->ECC_X1[i]; + } + +#if ENABLE_DEBUG + CRPT_DBGMSG("e = %s\n", message); + Reg2Hex(pCurve->Echar, temp_result2, temp_hex_str); + CRPT_DBGMSG("w = %s\n", temp_hex_str); + CRPT_DBGMSG("o = %s (order)\n", pCurve->Eorder); +#endif + + /* + * 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 + * (4) Set MOPOP(CRPT_ECC_CTL[12:11]) to 01 + * (5) Set START(CRPT_ECC_CTL[0]) to 1 + * (6) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (7) Read X1 registers to get u1 + * (8) Write the curve order and curve length to N ,M registers + * (9) Write r, w to X1, Y1 registers + * (10) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 + * (11) Set MOPOP(CRPT_ECC_CTL[12:11]) to 01 + * (12) Set START(CRPT_ECC_CTL[0]) to 1 + * (13) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (14) Read X1 registers to get u2 + */ + + /* 4-(1) Write the curve order and curve length to N ,M registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 4-(2) Write e, w to X1, Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = 0UL; + } + Hex2Reg(message, crpt->ECC_X1); + + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = temp_result2[i]; + } + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_MUL); + + /* 4-(7) Read X1 registers to get u1 */ + for (i = 0; i < 18; i++) + { + temp_result1[i] = crpt->ECC_X1[i]; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, temp_result1, temp_hex_str); + CRPT_DBGMSG("u1 = %s\n", temp_hex_str); +#endif + + /* 4-(8) Write the curve order and curve length to N ,M registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* 4-(9) Write r, w to X1, Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = 0UL; + } + Hex2Reg(R, crpt->ECC_X1); + + for (i = 0; i < 18; i++) + { + crpt->ECC_Y1[i] = temp_result2[i]; + } + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_MUL); + + /* 4-(14) Read X1 registers to get u2 */ + for (i = 0; i < 18; i++) + { + temp_result2[i] = crpt->ECC_X1[i]; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, temp_result2, temp_hex_str); + CRPT_DBGMSG("u2 = %s\n", temp_hex_str); +#endif + + /* + * 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 + * (4) Set ECCOP(CRPT_ECC_CTL[10:9]) to 00 + * (5) Set START(CRPT_ECC_CTL[0]) to 1 + * (6) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (7) Read X1, Y1 registers to get u1*G + * (8) Write the curve parameter A, B, N, and curve length M to corresponding registers + * (9) Write the public key Q(x,y) to X1, Y1 registers + * (10) Write u2 to K registers + * (11) Set ECCOP(CRPT_ECC_CTL[10:9]) to 00 + * (12) Set START(CRPT_ECC_CTL[0]) to 1 + * (13) Wait for BUSY(CRPT_ECC_STS[0]) be cleared + * (14) Write the curve parameter A, B, N, and curve length M to corresponding registers + * (15) Write the result data u1*G to X2, Y2 registers + * (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¡¦) + * (20) Write the curve order and curve length to N ,M 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) + * + * 6. The signature is valid if x1¡¦ = r, otherwise it is invalid + */ + + /* + * (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 + */ + ecc_init_curve(crpt, ecc_curve); + + /* (3) Write u1 to K registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_K[i] = temp_result1[i]; + } + + run_ecc_codec(crpt, ECCOP_POINT_MUL); + + /* (7) Read X1, Y1 registers to get u1*G */ + for (i = 0; i < 18; i++) + { + temp_x[i] = crpt->ECC_X1[i]; + temp_y[i] = crpt->ECC_Y1[i]; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, temp_x, temp_hex_str); + CRPT_DBGMSG("5-(7) u1*G, x = %s\n", temp_hex_str); + Reg2Hex(pCurve->Echar, temp_y, temp_hex_str); + CRPT_DBGMSG("5-(7) u1*G, y = %s\n", temp_hex_str); +#endif + + /* (8) Write the curve parameter A, B, N, and curve length M to corresponding registers */ + ecc_init_curve(crpt, ecc_curve); + + /* (9) Write the public key Q(x,y) to X1, Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = 0UL; + crpt->ECC_Y1[i] = 0UL; + } + + Hex2Reg(public_k1, crpt->ECC_X1); + Hex2Reg(public_k2, crpt->ECC_Y1); + + /* (10) Write u2 to K registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_K[i] = temp_result2[i]; + } + + run_ecc_codec(crpt, ECCOP_POINT_MUL); + + for (i = 0; i < 18; i++) + { + temp_result1[i] = crpt->ECC_X1[i]; + temp_result2[i] = crpt->ECC_Y1[i]; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, temp_result1, temp_hex_str); + CRPT_DBGMSG("5-(13) u2*Q, x = %s\n", temp_hex_str); + Reg2Hex(pCurve->Echar, temp_result2, temp_hex_str); + CRPT_DBGMSG("5-(13) u2*Q, y = %s\n", temp_hex_str); +#endif + + /* (14) Write the curve parameter A, B, N, and curve length M to corresponding registers */ + ecc_init_curve(crpt, ecc_curve); + + /* Write the result data u2*Q to X1, Y1 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = temp_result1[i]; + crpt->ECC_Y1[i] = temp_result2[i]; + } + + /* (15) Write the result data u1*G to X2, Y2 registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X2[i] = temp_x[i]; + crpt->ECC_Y2[i] = temp_y[i]; + } + + run_ecc_codec(crpt, ECCOP_POINT_ADD); + + /* (19) Read X1, Y1 registers to get X¡¦(x1¡¦, y1¡¦) */ + for (i = 0; i < 18; i++) + { + temp_x[i] = crpt->ECC_X1[i]; + temp_y[i] = crpt->ECC_Y1[i]; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, temp_x, temp_hex_str); + CRPT_DBGMSG("5-(19) x' = %s\n", temp_hex_str); + Reg2Hex(pCurve->Echar, temp_y, temp_hex_str); + CRPT_DBGMSG("5-(19) y' = %s\n", temp_hex_str); +#endif + + /* (20) Write the curve order and curve length to N ,M registers */ + for (i = 0; i < 18; i++) + { + crpt->ECC_N[i] = 0UL; + } + Hex2Reg(pCurve->Eorder, crpt->ECC_N); + + /* + * (21) Write x1¡¦ to X1 registers + * (22) Write 0x0 to Y1 registers + */ + for (i = 0; i < 18; i++) + { + crpt->ECC_X1[i] = temp_x[i]; + crpt->ECC_Y1[i] = 0UL; + } + +#if ENABLE_DEBUG + Reg2Hex(pCurve->Echar, crpt->ECC_X1, temp_hex_str); + CRPT_DBGMSG("5-(21) x' = %s\n", temp_hex_str); + Reg2Hex(pCurve->Echar, crpt->ECC_Y1, temp_hex_str); + CRPT_DBGMSG("5-(22) y' = %s\n", temp_hex_str); +#endif + + run_ecc_codec(crpt, ECCOP_MODULE | MODOP_ADD); + + /* (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 */ + + /* Compare with test pattern to check if r is correct or not */ + if (ecc_strcmp(temp_hex_str, R) != 0) + { + CRPT_DBGMSG("x1' (mod n) != R Test filed!!\n"); + CRPT_DBGMSG("Signature R [%s] is not matched with expected R [%s]!\n", temp_hex_str, R); + ret = -2; + } + } /* ret == 0 */ + + return ret; +} + + +/*-----------------------------------------------------------------------------------------------*/ +/* */ +/* RSA */ +/* */ +/*-----------------------------------------------------------------------------------------------*/ + +/** @cond HIDDEN_SYMBOLS */ + +#define MAX_DIGIT 0xFFFFFFFFUL +#define MAX_HALF_DIGIT 0xFFFFUL /* NB 'L' */ +#define BITS_PER_DIGIT 32 +#define HIBITMASK 0x80000000UL + +#define MAX_FIXED_BIT_LENGTH 8192 +#define MAX_FIXED_DIGITS ((MAX_FIXED_BIT_LENGTH + BITS_PER_DIGIT - 1) / BITS_PER_DIGIT) + +#ifndef max + #define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + + +static uint32_t qq[MAX_FIXED_DIGITS * 2]; +static uint32_t rr[MAX_FIXED_DIGITS * 2]; + + +/** Returns number of significant digits in a */ +static int mpSizeof(const uint32_t a[], int ndigits) +{ + while (ndigits--) + { + if (a[ndigits] != 0) + return (++ndigits); + } + return 0; +} + + +static int mpBitLength(const uint32_t d[], int ndigits) +/* Returns no of significant bits in d */ +{ + int n, i, bits; + uint32_t mask; + + if (!d || ndigits == 0) + return 0; + + n = mpSizeof(d, ndigits); + if (0 == n) return 0; + + for (i = 0, mask = HIBITMASK; mask > 0; mask >>= 1, i++) + { + if (d[n - 1] & mask) + break; + } + bits = n * BITS_PER_DIGIT - i; + return bits; +} + +static int mpGetBit(const uint32_t a[], int ndigits, int ibit) +/* Returns value 1 or 0 of bit n (0..nbits-1); or -1 if out of range */ +{ + int idigit, bit_to_get; + uint32_t mask; + + /* Which digit? (0-based) */ + idigit = ibit / BITS_PER_DIGIT; + if (idigit >= ndigits) + return -1; + + /* Set mask */ + bit_to_get = ibit % BITS_PER_DIGIT; + mask = 0x01 << bit_to_get; + + return ((a[idigit] & mask) ? 1 : 0); +} + +static uint32_t mpSetZero(volatile uint32_t a[], int ndigits) +{ + /* Sets a = 0 */ + + /* Prevent optimiser ignoring this */ + volatile uint32_t optdummy; + volatile uint32_t *p = a; + + while (ndigits--) + a[ndigits] = 0; + + optdummy = *p; + return optdummy; +} + +static void mpSetEqual(uint32_t a[], const uint32_t b[], int ndigits) +{ + /* Sets a = b */ + int i; + + for (i = 0; i < ndigits; i++) + { + a[i] = b[i]; + } +} + +static void mpSetDigit(uint32_t a[], uint32_t d, int ndigits) +{ + /* Sets a = d where d is a single digit */ + int i; + + for (i = 1; i < ndigits; i++) + { + a[i] = 0; + } + a[0] = d; +} + +/** Returns sign of (a - b) as 0, +1 or -1. Not constant-time. */ +static int mpCompare(const uint32_t a[], const uint32_t b[], int ndigits) +{ + /* if (ndigits == 0) return 0; // deleted [v2.5] */ + + while (ndigits--) + { + if (a[ndigits] > b[ndigits]) + return 1; /* GT */ + if (a[ndigits] < b[ndigits]) + return -1; /* LT */ + } + + return 0; /* EQ */ +} + +static uint32_t mpShiftLeft(uint32_t a[], const uint32_t *b, + int shift, int ndigits) +{ + /* Computes a = b << shift */ + /* [v2.1] Modified to cope with shift > BITS_PERDIGIT */ + int i, y, nw, bits; + uint32_t mask, carry, nextcarry; + + /* Do we shift whole digits? */ + if (shift >= BITS_PER_DIGIT) + { + nw = shift / BITS_PER_DIGIT; + i = ndigits; + while (i--) + { + if (i >= nw) + a[i] = b[i - nw]; + else + a[i] = 0; + } + /* Call again to shift bits inside digits */ + bits = shift % BITS_PER_DIGIT; + carry = b[ndigits - nw] << bits; + if (bits) + carry |= mpShiftLeft(a, a, bits, ndigits); + return carry; + } + else + { + bits = shift; + } + + /* Construct mask = high bits set */ + mask = ~(~(uint32_t)0 >> bits); + + y = BITS_PER_DIGIT - bits; + carry = 0; + for (i = 0; i < ndigits; i++) + { + nextcarry = (b[i] & mask) >> y; + a[i] = b[i] << bits | carry; + carry = nextcarry; + } + + return carry; +} + +static uint32_t mpShiftRight(uint32_t a[], const uint32_t b[], int shift, int ndigits) +{ + /* Computes a = b >> shift */ + /* [v2.1] Modified to cope with shift > BITS_PERDIGIT */ + int i, y, nw, bits; + uint32_t mask, carry, nextcarry; + + /* Do we shift whole digits? */ + if (shift >= BITS_PER_DIGIT) + { + nw = shift / BITS_PER_DIGIT; + for (i = 0; i < ndigits; i++) + { + if ((i + nw) < ndigits) + a[i] = b[i + nw]; + else + a[i] = 0; + } + /* Call again to shift bits inside digits */ + bits = shift % BITS_PER_DIGIT; + carry = b[nw - 1] >> bits; + if (bits) + carry |= mpShiftRight(a, a, bits, ndigits); + return carry; + } + else + { + bits = shift; + } + + /* Construct mask to set low bits */ + /* (thanks to Jesse Chisholm for suggesting this improved technique) */ + mask = ~(~(uint32_t)0 << bits); + + y = BITS_PER_DIGIT - bits; + carry = 0; + i = ndigits; + while (i--) + { + nextcarry = (b[i] & mask) << y; + a[i] = b[i] >> bits | carry; + carry = nextcarry; + } + + return carry; +} + +static uint32_t spDivide(uint32_t *pq, uint32_t *pr, const uint32_t u[2], uint32_t v) +{ + uint64_t uu, q; + uu = (uint64_t)u[1] << 32 | (uint64_t)u[0]; + q = uu / (uint64_t)v; + //r = uu % (uint64_t)v; + *pr = (uint32_t)(uu - q * v); + *pq = (uint32_t)(q & 0xFFFFFFFF); + return (uint32_t)(q >> 32); +} + +static int spMultiply(uint32_t p[2], uint32_t x, uint32_t y) +{ + /* Use a 64-bit temp for product */ + uint64_t t = (uint64_t)x * (uint64_t)y; + /* then split into two parts */ + p[1] = (uint32_t)(t >> 32); + p[0] = (uint32_t)(t & 0xFFFFFFFF); + + return 0; +} + +static uint32_t mpMultSub(uint32_t wn, uint32_t w[], const uint32_t v[], + uint32_t q, int n) +{ + /* Compute w = w - qv + where w = (WnW[n-1]...W[0]) + return modified Wn. + */ + uint32_t k, t[4]; + int i; + + if (q == 0) /* No change */ + return wn; + + k = 0; + + for (i = 0; i < n; i++) + { + spMultiply(t, q, v[i]); + w[i] -= k; + if (w[i] > MAX_DIGIT - k) + k = 1; + else + k = 0; + w[i] -= t[0]; + if (w[i] > MAX_DIGIT - t[0]) + k++; + k += t[1]; + } + + /* Cope with Wn not stored in array w[0..n-1] */ + wn -= k; + + return wn; +} + +static uint32_t mpShortDiv(uint32_t q[], const uint32_t u[], uint32_t v, + int ndigits) +{ + /* Calculates quotient q = u div v + Returns remainder r = u mod v + where q, u are multiprecision integers of ndigits each + and r, v are single precision digits. + + Makes no assumptions about normalisation. + + Ref: Knuth Vol 2 Ch 4.3.1 Exercise 16 p625 + */ + int j; + uint32_t t[4], r; + int shift; + uint32_t bitmask, overflow, *uu; + + if (ndigits == 0) return 0; + if (v == 0) return 0; /* Divide by zero error */ + + /* Normalise first */ + /* Requires high bit of V + to be set, so find most signif. bit then shift left, + i.e. d = 2^shift, u' = u * d, v' = v * d. + */ + bitmask = HIBITMASK; + for (shift = 0; shift < BITS_PER_DIGIT; shift++) + { + if (v & bitmask) + break; + bitmask >>= 1; + } + + v <<= shift; + overflow = mpShiftLeft(q, u, shift, ndigits); + uu = q; + + /* Step S1 - modified for extra digit. */ + r = overflow; /* New digit Un */ + j = ndigits; + while (j--) + { + /* Step S2. */ + t[1] = r; + t[0] = uu[j]; + overflow = spDivide(&q[j], &r, t, v); + } + + /* Unnormalise */ + r >>= shift; + + return r; +} + +static int QhatTooBig(uint32_t qhat, uint32_t rhat, + uint32_t vn2, uint32_t ujn2) +{ + /* Returns true if Qhat is too big + i.e. if (Qhat * Vn-2) > (b.Rhat + Uj+n-2) + */ + uint32_t t[4]; + + spMultiply(t, qhat, vn2); + if (t[1] < rhat) + return 0; + else if (t[1] > rhat) + return 1; + else if (t[0] > ujn2) + return 1; + + return 0; +} + +static uint32_t mpAdd(uint32_t w[], const uint32_t u[], const uint32_t v[], int ndigits) +{ + /* Calculates w = u + v + where w, u, v are multiprecision integers of ndigits each + Returns carry if overflow. Carry = 0 or 1. + + Ref: Knuth Vol 2 Ch 4.3.1 p 266 Algorithm A. + */ + + uint32_t k; + int j; + + // assert(w != v); + + /* Step A1. Initialise */ + k = 0; + + for (j = 0; j < ndigits; j++) + { + /* Step A2. Add digits w_j = (u_j + v_j + k) + Set k = 1 if carry (overflow) occurs + */ + w[j] = u[j] + k; + if (w[j] < k) + k = 1; + else + k = 0; + + w[j] += v[j]; + if (w[j] < v[j]) + k++; + + } /* Step A3. Loop on j */ + + return k; /* w_n = k */ +} + +static int mpDivide(uint32_t q[], uint32_t r[], const uint32_t u[], + int udigits, uint32_t v[], int vdigits) +{ + /* Computes quotient q = u / v and remainder r = u mod v + where q, r, u are multiple precision digits + all of udigits and the divisor v is vdigits. + + Ref: Knuth Vol 2 Ch 4.3.1 p 272 Algorithm D. + + Do without extra storage space, i.e. use r[] for + normalised u[], unnormalise v[] at end, and cope with + extra digit Uj+n added to u after normalisation. + + WARNING: this trashes q and r first, so cannot do + u = u / v or v = u mod v. + It also changes v temporarily so cannot make it const. + */ + int shift; + int n, m, j; + uint32_t bitmask, overflow; + uint32_t qhat, rhat, t[4]; + uint32_t *uu, *ww; + int qhatOK, cmp; + + /* Clear q and r */ + mpSetZero(q, udigits); + mpSetZero(r, udigits); + + /* Work out exact sizes of u and v */ + n = (int)mpSizeof(v, vdigits); + m = (int)mpSizeof(u, udigits); + m -= n; + + /* Catch special cases */ + if (n == 0) + return -1; /* Error: divide by zero */ + + if (n == 1) + { + /* Use short division instead */ + r[0] = mpShortDiv(q, u, v[0], udigits); + return 0; + } + + if (m < 0) + { + /* v > u, so just set q = 0 and r = u */ + mpSetEqual(r, u, udigits); + return 0; + } + + if (m == 0) + { + /* u and v are the same length */ + cmp = mpCompare(u, v, (int)n); + if (cmp < 0) + { + /* v > u, as above */ + mpSetEqual(r, u, udigits); + return 0; + } + else if (cmp == 0) + { + /* v == u, so set q = 1 and r = 0 */ + mpSetDigit(q, 1, udigits); + return 0; + } + } + + /* In Knuth notation, we have: + Given + u = (Um+n-1 ... U1U0) + v = (Vn-1 ... V1V0) + Compute + q = u/v = (QmQm-1 ... Q0) + r = u mod v = (Rn-1 ... R1R0) + */ + + /* Step D1. Normalise */ + /* Requires high bit of Vn-1 + to be set, so find most signif. bit then shift left, + i.e. d = 2^shift, u' = u * d, v' = v * d. + */ + bitmask = HIBITMASK; + for (shift = 0; shift < BITS_PER_DIGIT; shift++) + { + if (v[n - 1] & bitmask) + break; + bitmask >>= 1; + } + + /* Normalise v in situ - NB only shift non-zero digits */ + overflow = mpShiftLeft(v, v, shift, n); + + /* Copy normalised dividend u*d into r */ + overflow = mpShiftLeft(r, u, shift, n + m); + uu = r; /* Use ptr to keep notation constant */ + + t[0] = overflow; /* Extra digit Um+n */ + + /* Step D2. Initialise j. Set j = m */ + for (j = m; j >= 0; j--) + { + /* Step D3. Set Qhat = [(b.Uj+n + Uj+n-1)/Vn-1] + and Rhat = remainder */ + qhatOK = 0; + t[1] = t[0]; /* This is Uj+n */ + t[0] = uu[j + n - 1]; + overflow = spDivide(&qhat, &rhat, t, v[n - 1]); + + /* Test Qhat */ + if (overflow) + { + /* Qhat == b so set Qhat = b - 1 */ + qhat = MAX_DIGIT; + rhat = uu[j + n - 1]; + rhat += v[n - 1]; + if (rhat < v[n - 1]) /* Rhat >= b, so no re-test */ + qhatOK = 1; + } + /* [VERSION 2: Added extra test "qhat && "] */ + if (qhat && !qhatOK && QhatTooBig(qhat, rhat, v[n - 2], uu[j + n - 2])) + { + /* If Qhat.Vn-2 > b.Rhat + Uj+n-2 + decrease Qhat by one, increase Rhat by Vn-1 + */ + qhat--; + rhat += v[n - 1]; + /* Repeat this test if Rhat < b */ + if (!(rhat < v[n - 1])) + if (QhatTooBig(qhat, rhat, v[n - 2], uu[j + n - 2])) + qhat--; + } + + + /* Step D4. Multiply and subtract */ + ww = &uu[j]; + overflow = mpMultSub(t[1], ww, v, qhat, (int)n); + + /* Step D5. Test remainder. Set Qj = Qhat */ + q[j] = qhat; + if (overflow) + { + /* Step D6. Add back if D4 was negative */ + q[j]--; + overflow = mpAdd(ww, ww, v, (int)n); + } + + t[0] = uu[j + n - 1]; /* Uj+n on next round */ + + } /* Step D7. Loop on j */ + + /* Clear high digits in uu */ + for (j = n; j < m + n; j++) + uu[j] = 0; + + /* Step D8. Unnormalise. */ + + mpShiftRight(r, r, shift, n); + mpShiftRight(v, v, shift, n); + + return 0; +} + +/***************************/ +static int mpModulo(uint32_t r[], const uint32_t u[], int udigits, + uint32_t v[], int vdigits) +{ + /* Computes r = u mod v + where r, v are multiprecision integers of length vdigits + and u is a multiprecision integer of length udigits. + r may overlap v. + + Note that r here is only vdigits long, + whereas in mpDivide it is udigits long. + + Use remainder from mpDivide function. + */ + + int nn = max(udigits, vdigits); + + // [v2.6] increased to two times + if (nn > (MAX_FIXED_DIGITS * 2)) + { + printf("Error!! mpModulo nn overflow!\n"); + return -1; + } + + /* rr[nn] = u mod v */ + mpDivide(qq, rr, u, udigits, v, vdigits); + + /* Final r is only vdigits long */ + mpSetEqual(r, rr, vdigits); + return 0; +} + + +static void Hex2Binary(char *input, char *output) +{ + int i, j, idx, n, klen; + char *p = (char *)input; + + klen = strlen(input); + + if ((klen + 3) > RSA_KBUF_HLEN) + { + printf("Hex2Binary overflow!! %d > %d\n", klen + 3, RSA_KBUF_HLEN); + } + + klen = strlen(input) * 4; + + memset(output, 0, RSA_KBUF_BLEN); + output[klen] = 0; + output[klen + 1] = 0; + + idx = klen - 1; + + for (i = 0; *p != 0; i++, p++) + { + if (input[i] <= '9') + { + n = input[i] - '0'; + } + else if (input[i] >= 'a') + { + n = input[i] - 'a' + 10; + } + else + { + n = input[i] - 'A' + 10; + } + + for (j = 3; j >= 0; j--) + { + output[idx--] = (n >> j) & 0x1; + } + } + if (idx != -1) + { + printf("Hex2Binary unexpected error!!\n"); + } +} + +static void Binary2Hex(int length, char *input, char *output) +{ + int i, idx, n, slen; + + memset(output, 0, RSA_KBUF_HLEN); + + slen = length / 4; + + idx = slen - 1; + + for (i = 0; i < length; i += 4) + { + n = (input[i]) | (input[i + 1] << 1) | (input[i + 2] << 2) | (input[i + 3] << 3); + if (n >= 10) + output[idx] = n - 10 + 'A'; + else + output[idx] = n + '0'; + idx--; + } + + if (idx != -1) + { + printf("Binary2Hex unecpected error! %d\n", idx); + } +} + +#define Hardware_length (2096) + +static uint32_t C_t[(2096 * 2) / 32]; +static uint32_t N_t[(2096 * 2) / 32]; + +static char C[RSA_KBUF_BLEN], N[RSA_KBUF_BLEN]; + +/** @endcond HIDDEN_SYMBOLS */ + + +/** + * @brief Calculate the constant value of Montgomery domain. + * @param[in] length RSA bit length. + * @param[in] rsa_N The base of modulus operation. + * @param[out] rsa_C The constant value of Montgomery domain required by NUC980 RSA engine. + */ +void RSA_Calculate_C(int length, char *rsa_N, char *rsa_C) +{ + int i, v, nbits; + uint32_t j; + int scale = (length + 2) * 2; + size_t word_size = (scale / 32) + 1; + + memset(rsa_C, 0, length / 4 + 2); + Hex2Binary(rsa_N, N); + + memset(C_t, 0, sizeof(C_t)); + C_t[word_size - 1] = (uint32_t)(1 << scale - (32 * (word_size - 1))); + + // convert char to uint32_t + memset(N_t, 0, sizeof(N_t)); + j = 0; + for (i = 0; i < length; i++) + { + if (N[i]) + { + j += 1 << (i % 32); + } + + if ((i % 32) == 31) + { + N_t[(i / 32)] = j; + j = 0; + } + } + mpModulo(C_t, C_t, word_size, N_t, word_size); + + // convert uint32_t to char + nbits = (int)mpBitLength(C_t, word_size); + for (i = Hardware_length; i >= 0; i--) + { + if (i > nbits) + C[i] = 0; + else + { + v = mpGetBit(C_t, word_size, i); + C[i] = v ? 1 : 0; + } + } + Binary2Hex(length, C, rsa_C); +} + +/** + * @brief RSA digital signature generation. + * @param[in] crpt Reference to Crypto module. + * @param[in] rsa_len RSA key length + * @param[in] n The modulus for both the public and private keys + * @param[in] d (n,d) is the private key + * @param[in] C The constant value of Montgomery domain. + * @param[in] msg The message to be signed. + * @param[out] sig The output signature. + * @return 0 Success. + * @return -1 Error + */ +int32_t RSA_GenerateSignature(CRPT_T *crpt, int rsa_len, char *n, char *d, char *C, + char *msg, char *sig) +{ + int i; + + for (i = 0; i < 128; i++) + { + crpt->RSA_N[i] = 0; + crpt->RSA_E[i] = 0; + crpt->RSA_M[i] = 0; + } + + Hex2Reg(n, (uint32_t *)&crpt->RSA_N[0]); + Hex2Reg(d, (uint32_t *)&crpt->RSA_E[0]); + Hex2Reg(msg, (uint32_t *)&crpt->RSA_M[0]); + Hex2Reg(C, (uint32_t *)&crpt->RSA_C[0]); + + CRPT->RSA_CTL = (rsa_len << CRPT_RSA_CTL_KEYLEN_Pos) | CRPT_RSA_CTL_START_Msk; + while (CRPT->RSA_STS & CRPT_RSA_STS_BUSY_Msk) ; + + Reg2Hex(rsa_len / 4, (uint32_t *)CRPT->RSA_M, sig); + return 0; +} + +/** + * @brief RSA digital signature generation. + * @param[in] crpt Reference to Crypto module. + * @param[in] rsa_len RSA key length + * @param[in] n The modulus for both the public and private keys + * @param[in] e (n,e) is the public key + * @param[in] C The constant value of Montgomery domain. + * @param[in] sig The signature to be verified. + * @param[out] msg The message to be compared. + * @return 0 Success. + * @return -1 Verify failed + */ +int32_t RSA_VerifySignature(CRPT_T *crpt, int rsa_len, char *n, char *e, char *C, + char *sig, char *msg) +{ + char output[RSA_KBUF_HLEN]; + int i; + + for (i = 0; i < 128; i++) + { + crpt->RSA_N[i] = 0; + crpt->RSA_E[i] = 0; + crpt->RSA_M[i] = 0; + } + + Hex2Reg(n, (uint32_t *)&crpt->RSA_N[0]); + Hex2Reg(e, (uint32_t *)&crpt->RSA_E[0]); + Hex2Reg(sig, (uint32_t *)&crpt->RSA_M[0]); + Hex2Reg(C, (uint32_t *)&crpt->RSA_C[0]); + + CRPT->RSA_CTL = (rsa_len << CRPT_RSA_CTL_KEYLEN_Pos) | CRPT_RSA_CTL_START_Msk; + while (CRPT->RSA_STS & CRPT_RSA_STS_BUSY_Msk) ; + + Reg2Hex(rsa_len / 4, (uint32_t *)CRPT->RSA_M, output); + + printf("RSA verify: %s\n", output); + + if (ecc_strcmp(output, msg) != 0) + { + CRPT_DBGMSG("RSA verify output [%s] is not matched with expected [%s]!\n", output, msg); + return -1; + } + return 0; +} + + + +/*@}*/ /* end of group CRYPTO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CRYPTO_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_ebi.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_ebi.c new file mode 100644 index 0000000000..92297f9a09 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_ebi.c @@ -0,0 +1,190 @@ +/**************************************************************************//** + * @file ebi.c + * @version V1.00 + * @brief NUC980 series External Bus Interface(EBI) driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nuc980.h" +#include "nu_ebi.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 + * - \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 + * @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) +{ + uint32_t u32Index0 = (uint32_t)&EBI->CTL0 + (uint32_t)u32Bank * 0x10U; + uint32_t u32Index1 = (uint32_t)&EBI->TCTL0 + (uint32_t)u32Bank * 0x10U; + volatile uint32_t *pu32EBICTL = (uint32_t *)(u32Index0); + volatile uint32_t *pu32EBITCTL = (uint32_t *)(u32Index1); + + 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_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_MCLKDIV_1 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk; + *pu32EBITCTL = 0x03003318U; + break; + + case EBI_TIMING_FAST: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_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_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk; + *pu32EBITCTL = 0x03003318U; + break; + + case EBI_TIMING_SLOW: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk)) | + (EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk; + *pu32EBITCTL = 0x07007738U; + break; + + case EBI_TIMING_VERYSLOW: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk)) | + (EBI_MCLKDIV_4 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk ; + *pu32EBITCTL = 0x07007738U; + break; + + case EBI_TIMING_SLOWEST: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk)) | + (EBI_MCLKDIV_8 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk; + *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 + * - \ref EBI_BANK2 + * + * @return None + * + * @details This function is used to close specify EBI function. + */ +void EBI_Close(uint32_t u32Bank) +{ + uint32_t u32Index = (uint32_t)&EBI->CTL0 + u32Bank * 0x10U; + volatile uint32_t *pu32EBICTL = (uint32_t *)(u32Index); + + *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 + * - \ref EBI_BANK2 + * @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 + * - \ref EBI_MCLKDIV_64 + * - \ref EBI_MCLKDIV_128 + * + * @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) +{ + uint32_t u32Index0 = (uint32_t)&EBI->CTL0 + (uint32_t)u32Bank * 0x10U; + uint32_t u32Index1 = (uint32_t)&EBI->TCTL0 + (uint32_t)u32Bank * 0x10U; + volatile uint32_t *pu32EBICTL = (uint32_t *)(u32Index0); + volatile uint32_t *pu32EBITCTL = (uint32_t *)(u32Index1); + + *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 2019 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c new file mode 100644 index 0000000000..92f5afc2a8 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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++ > 2000000UL) /* Cable not connected */ + { + EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; + EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; + break; + } + } + + if (i <= 2000000UL) + { + /* 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/nuc980/Driver/Source/nu_etimer.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_etimer.c new file mode 100644 index 0000000000..41d927c122 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_etimer.c @@ -0,0 +1,490 @@ +/**************************************************************************//** + * @file etimer.c + * @brief ETIMER driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nuc980.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 ~ 5 + * @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 * 2)) & 0x3; + + if (src == 0) + return 12000000; + else if (src == 1) + return (sysGetClock(SYS_PCLK01) * 1000000); + else if (src == 2) + return (sysGetClock(SYS_PCLK01) * 1000000 / 4096); + else + return 32768; + +} + +/// @endcond /* HIDDEN_SYMBOLS */ + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup ETIMER_Driver ETIMER Driver + @{ +*/ + + +/** @addtogroup 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 ~ 5 + * @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 >= 0x8000000) + { + u32Prescale = 15; // real prescaler value is 16 + u32Clk >>= 4; + } + 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 if (timer == 3) + { + outpw(REG_ETMR3_CMPR, u32Cmpr); + outpw(REG_ETMR3_PRECNT, u32Prescale); + outpw(REG_ETMR3_CTL, 1 | u32Mode); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CMPR, u32Cmpr); + outpw(REG_ETMR4_PRECNT, u32Prescale); + outpw(REG_ETMR4_CTL, 1 | u32Mode); + } + else + { + outpw(REG_ETMR5_CMPR, u32Cmpr); + outpw(REG_ETMR5_PRECNT, u32Prescale); + outpw(REG_ETMR5_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 ~ 5 + * @return None + */ +void ETIMER_Close(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, 0); + outpw(REG_ETMR0_IER, 0); + outpw(REG_ETMR0_DR, 0); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, 0); + outpw(REG_ETMR1_IER, 0); + outpw(REG_ETMR1_DR, 0); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, 0); + outpw(REG_ETMR2_IER, 0); + outpw(REG_ETMR2_DR, 0); + } + else if (timer == 3) + { + outpw(REG_ETMR3_CTL, 0); + outpw(REG_ETMR3_IER, 0); + outpw(REG_ETMR3_DR, 0); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, 0); + outpw(REG_ETMR4_IER, 0); + outpw(REG_ETMR4_DR, 0); + } + else + { + outpw(REG_ETMR5_CTL, 0); + outpw(REG_ETMR5_IER, 0); + outpw(REG_ETMR5_DR, 0); + } +} + +/** + * @brief This API is used to create a delay loop for u32usec micro seconds + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, 0); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, 0); + } + else + { + outpw(REG_ETMR5_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 if (timer == 3) + { + outpw(REG_ETMR3_CMPR, (UINT)fCmpr); + outpw(REG_ETMR3_PRECNT, u32Prescale); + outpw(REG_ETMR3_CTL, 1); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CMPR, (UINT)fCmpr); + outpw(REG_ETMR4_PRECNT, u32Prescale); + outpw(REG_ETMR4_CTL, 1); + } + else + { + outpw(REG_ETMR5_CMPR, (UINT)fCmpr); + outpw(REG_ETMR5_PRECNT, u32Prescale); + outpw(REG_ETMR5_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 if (timer == 3) + { + while (inpw(REG_ETMR3_CTL) & 0x80); + } + else if (timer == 4) + { + while (inpw(REG_ETMR4_CTL) & 0x80); + } + else + { + while (inpw(REG_ETMR5_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 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, (inpw(REG_ETMR3_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, (inpw(REG_ETMR4_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } + else + { + outpw(REG_ETMR5_CTL, (inpw(REG_ETMR5_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } +} + +/** + * @brief This API is used to disable the Timer capture function + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @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 if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~0x10000); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) & ~0x10000); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) & ~0x10000); + } + +} + +/** + * @brief This function is used to enable the Timer counter function with specify detection edge + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @param[in] u32Edge Detection edge of counter pin. Could be ether + * - \ref TIMER_COUNTER_RISING_EDGE, or + * - \ref TIMER_COUNTER_FALLING_EDGE + * @return None + * @note Timer compare value should be configured separately by using \ref ETIMER_SET_CMP_VALUE macro or program registers directly + */ +void ETIMER_EnableEventCounter(UINT timer, uint32_t u32Edge) +{ + + if (timer == 0) + { + outpw(REG_ETMR0_CTL, (inpw(REG_ETMR0_CTL) & ~0x2000) | u32Edge | 0x1000); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, (inpw(REG_ETMR1_CTL) & ~0x2000) | u32Edge | 0x1000); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, (inpw(REG_ETMR2_CTL) & ~0x2000) | u32Edge | 0x1000); + } + else if (timer == 3) + { + outpw(REG_ETMR3_CTL, (inpw(REG_ETMR3_CTL) & ~0x2000) | u32Edge | 0x1000); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, (inpw(REG_ETMR4_CTL) & ~0x2000) | u32Edge | 0x1000); + } + else + { + outpw(REG_ETMR5_CTL, (inpw(REG_ETMR5_CTL) & ~0x2000) | u32Edge | 0x1000); + } + +} + +/** + * @brief This API is used to disable the Timer event counter function. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @return None + */ +void ETIMER_DisableEventCounter(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) & ~0x1000); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) & ~0x1000); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) & ~0x1000); + } + else if (timer == 3) + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~0x1000); + } + else if (timer == 4) + { + outpw(REG_ETMR4_CTL, inpw(REG_ETMR4_CTL) & ~0x1000); + } + else + { + outpw(REG_ETMR5_CTL, inpw(REG_ETMR5_CTL) & ~0x1000); + } +} + + +/*@}*/ /* end of group ETIMER_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group ETIMER_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_gpio.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_gpio.c new file mode 100644 index 0000000000..745c37595c --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_gpio.c @@ -0,0 +1,151 @@ +/**************************************************************************//** + * @file gpio.c + * @brief GPIO driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include "nuc980.h" +#include "nu_gpio.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 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, PC, PD, PF and PH GPIO port. + * It could be BIT0 ~ BIT13 for PE GPIO port. + * It could be BIT0 ~ BIT11 for PG GPIO port. + * @param[in] u32Mode Operation mode. It could be \n + * GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_OPEN_DRAIN. + * + * @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 = 0ul; i < GPIO_PIN_MAX; i++) + { + if ((u32PinMask & (1ul << i)) == (1ul << i)) + { + port->MODE = (port->MODE & ~(0x3ul << (i << 1))) | (u32Mode << (i << 1)); + } + } +} + +/** + * @brief Enable GPIO interrupt + * + * @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port. + * It could be 0 ~ 13 for PE GPIO port. + * It could be 0 ~ 11 for PG GPIO port. + * @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n + * GPIO_INT_RISING, GPIO_INT_FALLING, GPIO_INT_BOTH_EDGE, GPIO_INT_HIGH, 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) +{ + port->INTTYPE |= (((u32IntAttribs >> 24) & 0xFFUL) << u32Pin); + port->INTEN |= ((u32IntAttribs & 0xFFFFFFUL) << u32Pin); +} + + +/** + * @brief Disable GPIO interrupt + * + * @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port. + * It could be 0 ~ 13 for PE GPIO port. + * It could be 0 ~ 11 for PG GPIO port. + * + * @return None + * + * @details This function is used to disable specified GPIO pin interrupt. + */ +void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin) +{ + port->INTTYPE &= ~(1UL << u32Pin); + port->INTEN &= ~((0x00010001UL) << u32Pin); +} + +/** + * @brief Set GPIO slew rate control + * + * @param[in] port GPIO port. It could be \ref PA, \ref PB, ... or \ref PG + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * @param[in] u32Mode Slew rate mode. \ref GPIO_SLEWCTL_NORMAL (maximum 40 MHz at 2.7V) + * \ref GPIO_SLEWCTL_HIGH (maximum 80 MHz at 2.7V) + * \ref GPIO_SLEWCTL_FAST (maximum 100 MHz at 2.7V) + * + * @return None + * + * @details This function is used to set specified GPIO operation mode. + */ +void GPIO_SetSlewCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode) +{ + uint32_t i; + + for (i = 0ul; i < GPIO_PIN_MAX; i++) + { + if (u32PinMask & (1ul << i)) + { + port->SLEWCTL = (port->SLEWCTL & ~(0x3ul << (i << 1))) | (u32Mode << (i << 1)); + } + } +} + +/** + * @brief Set GPIO Pull-up and Pull-down control + * + * @param[in] port GPIO port. It could be \ref PA, \ref PB, ... or \ref PG + * @param[in] u32PinMask The pin of specified GPIO port. It could be 0 ~ 15. + * @param[in] u32Mode The pin mode of specified GPIO pin. It could be + * \ref GPIO_PUSEL_DISABLE + * \ref GPIO_PUSEL_PULL_UP + * \ref GPIO_PUSEL_PULL_DOWN + * + * @return None + * + * @details Set the pin mode of specified GPIO pin. + */ +void GPIO_SetPullCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode) +{ + uint32_t i; + + for (i = 0ul; i < GPIO_PIN_MAX; i++) + { + if (u32PinMask & (1ul << i)) + { + port->PUSEL = (port->PUSEL & ~(0x3ul << (i << 1))) | (u32Mode << (i << 1)); + } + } +} + + +/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group GPIO_Driver */ + +/*@}*/ /* end of group Standard_Driver */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2c.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2c.c new file mode 100644 index 0000000000..0b71907ebb --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2c.c @@ -0,0 +1,1243 @@ +/**************************************************************************//** + * @file i2c.c + * @version V3.00 + * @brief NUC980 series I2C driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "nu_i2c.h" +#include "nu_sys.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; + + u32Pclk = (sysGetClock(SYS_PCLK01)) * 1000000; + + 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 ((uint32_t)i2c == I2C0_BA) + { + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 0)); + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 0)); + } + else if ((uint32_t)i2c == I2C1_BA) + { + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 1)); + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 1)); + } + else if ((uint32_t)i2c == I2C2_BA) + { + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 2)); + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 2)); + } + else if ((uint32_t)i2c == I2C3_BA) + { + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 3)); + outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 3)); + } + + + /* 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; + + u32Pclk = (sysGetClock(SYS_PCLK01)) * 1000000; + + 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; + + u32Pclk = (sysGetClock(SYS_PCLK01)) * 1000000; + + 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) +{ + uint32_t u32Value; + + if ((i2c->CTL0 & I2C_CTL0_SI_Msk) == I2C_CTL0_SI_Msk) + { + u32Value = 1U; + } + else + { + u32Value = 0U; + } + + return u32Value; +} + +/** + * @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 (I2CADDR0~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) | u8GCMode; + break; + case 2: + i2c->ADDR2 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode; + break; + case 3: + i2c->ADDR3 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode; + 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 I2CTOC 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 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, data); /* Write data to I2CDAT */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + case 0x28u: + 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 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Send Slave address with write bit */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + if (u32txLen < 1u) + { + I2C_SET_DATA(i2c, data); + u32txLen++; + } + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + } + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + if (u32txLen < u32wLen) + { + I2C_SET_DATA(i2c, data[u32txLen++]); + } + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + } + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + 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 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 a byte 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + 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 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x40u: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x48u: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x58u: + rdata = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x40u: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + break; + case 0x48u: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x50u: + rdata[u32rxLen++] = (unsigned char) 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 0x58u: + rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */ + break; + case 0x10u: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x40u: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x48u: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x58u: + rdata = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 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 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */ + break; + case 0x10u: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x40u: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + break; + case 0x48u: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x50u: + 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 0x58u: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + 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 0x10u: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x40u: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x48u: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x58u: + rdata = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 0x08u: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x18u: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */ + break; + case 0x20u: /* Slave Address NACK */ + case 0x30u: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x28u: + 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 0x10u: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + case 0x40u: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + break; + case 0x48u: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1u; + break; + case 0x50u: + rdata[u32rxLen++] = (unsigned char) 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 0x58u: + rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0u; + break; + case 0x38u: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + 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 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. + */ +void I2C_STOP(I2C_T *i2c) +{ + + (i2c)->CTL0 |= (I2C_CTL0_SI_Msk | I2C_CTL0_STO_Msk); + while (i2c->CTL0 & I2C_CTL0_STO_Msk) + { + } +} + +/*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group I2C_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2s.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2s.c new file mode 100644 index 0000000000..0203310f06 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_i2s.c @@ -0,0 +1,466 @@ +/**************************************************************************//** +* @file i2s.c +* @version V1.00 +* $Revision: 4 $ +* $Date: 18/08/05 2:12p $ +* @brief I2S driver source file +* +* @note + * SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include + +#include "nuc980.h" +#include "nu_sys.h" +#include "nu_i2s.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup I2S_Driver I2S Driver + @{ +*/ + +/** @addtogroup 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 ARM9_I2S_EXPORTED_CONSTANTS */ + +/** @addtogroup ARM9_I2S_EXPORTED_FUNCTIONS I2S Exported Functions + @{ +*/ + +/// @cond HIDDEN_SYMBOLS +/** + * @brief Start to play + * @param None + * @return None + */ +static void i2sStartPlay(void) +{ + /* start playing */ + printf("IIS start playing...\n"); + + outpw(REG_I2S_PSR, 0x1); + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) | (1 << 5)); +} + +/** + * @brief Stop to play + * @param None + * @return None + */ +static void i2sStopPlay(void) +{ + printf("IIS stop playing\n"); + + /* stop playing */ + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) & ~(1 << 5)); +} + +/** + * @brief Start to record + * @param None + * @return None + */ +static void i2sStartRecord(void) +{ + /* start recording */ + printf("IIS start recording...\n"); + + outpw(REG_I2S_RSR, 0x1); + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) | (1 << 6)); +} + +/** + * @brief Stop to record + * @param None + * @return None + */ +static void i2sStopRecord(void) +{ + printf("I2S stop recording\n"); + + /* stop recording */ + outpw(REG_I2S_RESET, inpw(REG_I2S_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_I2S_CON) & (1 << 10)) + { + outpw(REG_I2S_CON, inpw(REG_I2S_CON) | (1 << 10)); //Clear TX INT + + if (inpw(REG_I2S_PSR) & (1 << 4)) + { + outpw(REG_I2S_PSR, (1 << 4)); + printf("\ndebug:DMA_COUNTER_IRQ occur"); + } + + if (inpw(REG_I2S_PSR) & (1 << 3)) + { + outpw(REG_I2S_PSR, (1 << 3)); + printf("\ndebug:DMA_DATA_ZERO_IRQ occur"); + } + + if (inpw(REG_I2S_PSR) & 0x1) + { + outpw(REG_I2S_PSR, 0x1); + u8SN = (inpw(REG_I2S_PSR) >> 5) & 0x7; + g_fnPlayCallBack(u8SN); + } + } + + if (inpw(REG_I2S_CON) & (1 << 11)) + { + outpw(REG_I2S_CON, inpw(REG_I2S_CON) | (1 << 11)); //Clear RX INT + + if (inpw(REG_I2S_RSR) & 0x1) + { + outpw(REG_I2S_RSR, 0x1); + u8SN = (inpw(REG_I2S_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_I2S_RESET, inpw(REG_I2S_RESET) | (1 << 16)); + Delay(100); + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) & ~(1 << 16)); + Delay(100); + + /* reset IIS interface */ + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) | 0x1); + Delay(100); + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) & ~0x1); + Delay(100); + + outpw(REG_I2S_CON, inpw(REG_I2S_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)); + + // disable i2s engine clock + outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) & ~(1 << 24)); +} + +/** + * @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 + sysInstallISR(IRQ_LEVEL_1, IRQ_I2S, (PVOID)i2sISR); + sysEnableInterrupt(IRQ_I2S); + 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 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_I2S_CON, (inpw(REG_I2S_CON) & ~0x3) | 0x1); + else + outpw(REG_I2S_CON, (inpw(REG_I2S_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_I2S_CON, (inpw(REG_I2S_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_I2S_CON, (inpw(REG_I2S_CON) & ~0x3000) | (arg0 << 12)); + break; + + case I2S_SET_REC_DMA_INT_SEL: + outpw(REG_I2S_CON, (inpw(REG_I2S_CON) & ~0xc000) | (arg0 << 14)); + break; + + case I2S_SET_ZEROCROSS: + if (arg0 == I2S_ENABLE) + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) | 0x8); + else + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) & ~0x8); + break; + + case I2S_SET_DMACOUNTER: + if (arg0 == I2S_ENABLE) + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) | 0x10); + else + outpw(REG_I2S_RESET, inpw(REG_I2S_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_I2S_RESET, inpw(REG_I2S_RESET) & ~(0x3 << 12) | (arg1 << 12)); + else + outpw(REG_I2S_RESET, inpw(REG_I2S_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_I2S_I2SCON, inpw(REG_I2S_I2SCON) & ~(0x1 << 20)); + else + outpw(REG_I2S_I2SCON, inpw(REG_I2S_I2SCON) | (0x1 << 20)); + break; + + case I2S_SET_SPLITDATA: + if (arg0 == I2S_ENABLE) + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) | (0x1 << 20)); + else + outpw(REG_I2S_RESET, inpw(REG_I2S_RESET) & ~(0x1 << 20)); + break; + + case I2S_SET_DMA_ADDRESS: + if (arg0 == I2S_PLAY) + outpw(REG_I2S_PDESB, arg1 | 0x80000000); + else if (arg0 == I2S_REC) + outpw(REG_I2S_RDESB, arg1 | 0x80000000); + else if (arg0 == PCM_PLAY) + outpw(REG_I2S_PDESB2, arg1 | 0x80000000); + else + outpw(REG_I2S_RDESB2, arg1 | 0x80000000); + break; + + case I2S_SET_DMA_LENGTH: + if (arg0 == I2S_PLAY) + outpw(REG_I2S_PDES_LENGTH, arg1); + else + outpw(REG_I2S_RDES_LENGTH, arg1); + break; + + case I2S_GET_DMA_CUR_ADDRESS: + buf = (uint32_t *)arg0; + if (arg0 == I2S_PLAY) + *buf = inpw(REG_I2S_PDESC); + else + *buf = inpw(REG_I2S_RDESC); + break; + + // #define I2S_FORMAT_I2S 0 + // #define I2S_FORMAT_MSB 1 + case I2S_SET_I2S_FORMAT: + if (arg0 == I2S_FORMAT_I2S) + outpw(REG_I2S_I2SCON, inpw(REG_I2S_I2SCON) & ~ 0x8); + else + outpw(REG_I2S_I2SCON, inpw(REG_I2S_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_I2S_PCMS1ST, (inpw(REG_I2S_PCMS1ST) & ~0x3ff) | (arg1 & 0x3ff)); + else if (arg0 == PCM_SLOT1_OUT) + outpw(REG_I2S_PCMS1ST, (inpw(REG_I2S_PCMS1ST) & ~0x3ff0000) | ((arg1 & 0x3ff) << 16)); + else if (arg0 == PCM_SLOT2_IN) + outpw(REG_I2S_PCMS2ST, (inpw(REG_I2S_PCMS2ST) & ~0x3ff) | (arg1 & 0x3ff)); + else + outpw(REG_I2S_PCMS2ST, (inpw(REG_I2S_PCMS2ST) & ~0x3ff0000) | ((arg1 & 0x3ff) << 16)); + break; + + case I2S_SET_PCM_FS_PERIOD: + outpw(REG_I2S_PCMCON, (inpw(REG_I2S_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_I2S_I2SCON, (inpw(REG_I2S_I2SCON) & ~0x000F0000) | (u32MCLKDiv - 1) << 16); + + u32BCLKDiv = u32MCLK / (u32SampleRate * u32DataBit * u32Channel); + u32BCLKDiv = u32BCLKDiv / 2 - 1; + outpw(REG_I2S_I2SCON, (inpw(REG_I2S_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_I2S_I2SCON, (inpw(REG_I2S_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_I2S_PCMCON, (inpw(REG_I2S_PCMCON) & ~0x0000FF00) | (u32BCLKDiv << 8)); +} + + +/*@}*/ /* end of group I2S_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group I2S_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_pdma.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_pdma.c new file mode 100644 index 0000000000..b3ababaec9 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_pdma.c @@ -0,0 +1,443 @@ +/**************************************************************************//** + * @file pdma.c + * @brief PDMA driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nuc980.h" +#include "nu_pdma.h" + + +static uint8_t u32ChSelect[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; + u32ChSelect[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 Stride Mode + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32DestLen Destination stride count + * @param[in] u32SrcLen Source stride count + * @param[in] u32TransCount Transfer count + * + * @return None + * + * @details This function set the selected stride mode. + */ +void PDMA_SetStride(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32DestLen, uint32_t u32SrcLen, uint32_t u32TransCount) +{ + pdma->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_STRIDEEN_Msk; + pdma->STRIDE[u32Ch].ASOCR = (u32DestLen << 16) | u32SrcLen; + pdma->STRIDE[u32Ch].STCR = u32TransCount; +} + +/** + * @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_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 + * - \ref PDMA_QSPI0_TX + * - \ref PDMA_QSPI0_RX + * - \ref PDMA_SPI0_TX + * - \ref PDMA_SPI0_RX + * - \ref PDMA_SPI1_TX + * - \ref PDMA_SPI1_RX + * - \ref PDMA_UART8_TX + * - \ref PDMA_UART8_RX + * - \ref PDMA_UART9_TX + * - \ref PDMA_UART9_RX + * - \ref PDMA_I2C0_TX + * - \ref PDMA_I2C0_RX + * - \ref PDMA_I2C1_TX + * - \ref PDMA_I2C1_RX + * - \ref PDMA_I2C2_TX + * - \ref PDMA_I2C2_RX + * - \ref PDMA_I2C3_TX + * - \ref PDMA_I2C3_RX + * - \ref PDMA_TIMER0 + * - \ref PDMA_TIMER1 + * - \ref PDMA_TIMER2 + * - \ref PDMA_TIMER3 + * - \ref PDMA_TIMER4 + * - \ref PDMA_TIMER5 + * @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) +{ + u32ChSelect[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_11 = (pdma->REQSEL8_11 & ~PDMA_REQSEL8_11_REQSRC8_Msk) | u32Peripheral; + break; + case 9ul: + pdma->REQSEL8_11 = (pdma->REQSEL8_11 & ~PDMA_REQSEL8_11_REQSRC9_Msk) | (u32Peripheral << PDMA_REQSEL8_11_REQSRC9_Pos); + 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. + */ +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; + case 2ul: + pdma->TOC2_3 = (pdma->TOC2_3 & ~PDMA_TOC2_3_TOC2_Msk) | u32TimeOutCnt; + break; + case 3ul: + pdma->TOC2_3 = (pdma->TOC2_3 & ~PDMA_TOC2_3_TOC3_Msk) | (u32TimeOutCnt << PDMA_TOC0_1_TOC1_Pos); + break; + case 4ul: + pdma->TOC4_5 = (pdma->TOC4_5 & ~PDMA_TOC4_5_TOC4_Msk) | u32TimeOutCnt; + break; + case 5ul: + pdma->TOC4_5 = (pdma->TOC4_5 & ~PDMA_TOC4_5_TOC5_Msk) | (u32TimeOutCnt << PDMA_TOC4_5_TOC5_Pos); + break; + case 6ul: + pdma->TOC6_7 = (pdma->TOC6_7 & ~PDMA_TOC6_7_TOC6_Msk) | u32TimeOutCnt; + break; + case 7ul: + pdma->TOC6_7 = (pdma->TOC6_7 & ~PDMA_TOC6_7_TOC7_Msk) | (u32TimeOutCnt << PDMA_TOC6_7_TOC7_Pos); + break; + case 8ul: + pdma->TOC8_9 = (pdma->TOC8_9 & ~PDMA_TOC8_9_TOC8_Msk) | u32TimeOutCnt; + break; + case 9ul: + pdma->TOC8_9 = (pdma->TOC8_9 & ~PDMA_TOC8_9_TOC9_Msk) | (u32TimeOutCnt << PDMA_TOC8_9_TOC9_Pos); + break; + default: + break; + } + if (u32OnOff) + pdma->TOUTEN |= (1 << u32Ch); + else + pdma->TOUTEN &= ~(1 << 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 (u32ChSelect[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 */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_qspi.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_qspi.c new file mode 100644 index 0000000000..f233927c94 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_qspi.c @@ -0,0 +1,598 @@ +/**************************************************************************//** + * @file qspi.c + * @brief NUC980 series QSPI driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nuc980.h" +#include "nu_qspi.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 u32RetValue = 0U; + + if (u32DataWidth == 32U) + { + u32DataWidth = 0U; + } + + 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_QSPIEN_Msk; + + /* Set DIVIDER */ + qspi->CLKDIV = ((150000000U / u32BusClock) - 1U); + } + 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_QSPIEN_Msk; + + /* Set DIVIDER = 0 */ + qspi->CLKDIV = 0U; + } + + 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 */ +} + +/** + * @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) +{ + return 0; +} + +/** + * @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 ~ 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 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) +{ + /* Return QSPI bus clock rate */ + return 0; +} + +/** + * @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_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 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_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 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_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_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_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_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_QSPIEN_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 = 0U, 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_QSPIENSTS_Msk; + /* Check QSPIEN flag */ + 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)) + { + 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/nuc980/Driver/Source/nu_rtc.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_rtc.c new file mode 100644 index 0000000000..1dab4c7a13 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_rtc.c @@ -0,0 +1,808 @@ +/**************************************************************************//** + * @file rtc.c + * @version V3.00 + * $Revision: 5 $ + * $Date: 14/06/10 5:49p $ + * @brief NUC980 series RTC driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nu_rtc.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] sPt 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 *sPt) +{ + RTC->INIT = RTC_INIT_KEY; + RTC_Check(); + + if (RTC->INIT != RTC_INIT_ACTIVE_Msk) + { + RTC->INIT = RTC_INIT_KEY; + while (RTC->INIT != RTC_INIT_ACTIVE_Msk) + { + } + } + + if (sPt == 0) + { + } + else + { + /* Set RTC date and time */ + RTC_SetDateAndTime(sPt); + } +} + +/** + * @brief Disable RTC Clock + * + * @param None + * + * @return None + * + * @details This API will disable RTC peripheral clock and stops RTC counting. + */ +void RTC_Close(void) +{ + outp32(REG_CLK_PCLKEN0, inp32(REG_CLK_PCLKEN0 & ~(0x1 << 1))); +} + +/** + * @brief Set Frequency Compensation Data + * + * @param[in] i32FrequencyX100 Specify the RTC clock X100, ex: 3277365 means 32773.65. + * + * @return None + * + */ +void RTC_32KCalibration(int32_t 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 = 0; + + if (i32RegInt > 15) i32RegInt = 15; + + u32Reg = (uint32_t)((i32RegInt << 8) | i32RegFra); + + RTC_WaitAccessEnable(); + outp32(REG_RTC_FREQADJ, u32Reg); + RTC_Check(); +} + +/** + * @brief Get Current RTC Date and Time + * + * @param[out] sPt 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 *sPt) +{ + uint32_t u32Tmp; + + sPt->u32TimeScale = RTC->CLKFMT & RTC_CLKFMT_24HEN_Msk; /* 12/24-hour */ + sPt->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; + sPt->u32Year = u32Tmp + RTC_YEAR2000; + + /* Compute 0~12 month */ + u32Tmp = (g_u32hiMonth * 10ul); + sPt->u32Month = u32Tmp + g_u32loMonth; + + /* Compute 0~31 day */ + u32Tmp = (g_u32hiDay * 10ul); + sPt->u32Day = u32Tmp + g_u32loDay; + + /* Compute 12/24 hour */ + if (sPt->u32TimeScale == RTC_CLOCK_12) + { + u32Tmp = (g_u32hiHour * 10ul); + u32Tmp += g_u32loHour; + sPt->u32Hour = u32Tmp; /* AM: 1~12. PM: 21~32. */ + + if (sPt->u32Hour >= 21ul) + { + sPt->u32AmPm = RTC_PM; + sPt->u32Hour -= 20ul; + } + else + { + sPt->u32AmPm = RTC_AM; + } + + u32Tmp = (g_u32hiMin * 10ul); + u32Tmp += g_u32loMin; + sPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32hiSec * 10ul); + u32Tmp += g_u32loSec; + sPt->u32Second = u32Tmp; + } + else + { + u32Tmp = (g_u32hiHour * 10ul); + u32Tmp += g_u32loHour; + sPt->u32Hour = u32Tmp; + + u32Tmp = (g_u32hiMin * 10ul); + u32Tmp += g_u32loMin; + sPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32hiSec * 10ul); + u32Tmp += g_u32loSec; + sPt->u32Second = u32Tmp; + } +} + +/** + * @brief Get RTC Alarm Date and Time + * + * @param[out] sPt 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 *sPt) +{ + uint32_t u32Tmp; + + sPt->u32TimeScale = RTC->CLKFMT & RTC_CLKFMT_24HEN_Msk; /* 12/24-hour */ + sPt->u32DayOfWeek = RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk; /* Day of the week */ + + /* Get alarm [Date digit] data */ + RTC_WaitAccessEnable(); + 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 */ + RTC_WaitAccessEnable(); + 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; + sPt->u32Year = u32Tmp + RTC_YEAR2000; + + /* Compute 0~12 month */ + u32Tmp = (g_u32hiMonth * 10ul); + sPt->u32Month = u32Tmp + g_u32loMonth; + + /* Compute 0~31 day */ + u32Tmp = (g_u32hiDay * 10ul); + sPt->u32Day = u32Tmp + g_u32loDay; + + /* Compute 12/24 hour */ + if (sPt->u32TimeScale == RTC_CLOCK_12) + { + u32Tmp = (g_u32hiHour * 10ul); + u32Tmp += g_u32loHour; + sPt->u32Hour = u32Tmp; /* AM: 1~12. PM: 21~32. */ + + if (sPt->u32Hour >= 21ul) + { + sPt->u32AmPm = RTC_PM; + sPt->u32Hour -= 20ul; + } + else + { + sPt->u32AmPm = RTC_AM; + } + + u32Tmp = (g_u32hiMin * 10ul); + u32Tmp += g_u32loMin; + sPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32hiSec * 10ul); + u32Tmp += g_u32loSec; + sPt->u32Second = u32Tmp; + + } + else + { + u32Tmp = (g_u32hiHour * 10ul); + u32Tmp += g_u32loHour; + sPt->u32Hour = u32Tmp; + + u32Tmp = (g_u32hiMin * 10ul); + u32Tmp += g_u32loMin; + sPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32hiSec * 10ul); + u32Tmp += g_u32loSec; + sPt->u32Second = u32Tmp; + } +} + +/** + * @brief Update Current RTC Date and Time + * + * @param[in] sPt 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 *sPt) +{ + uint32_t u32RegCAL, u32RegTIME; + + if (sPt == 0ul) + { + } + else + { + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC 24/12 hour setting and Day of the Week */ + /*-----------------------------------------------------------------------------------------------------*/ + RTC_WaitAccessEnable(); + if (sPt->u32TimeScale == RTC_CLOCK_12) + { + RTC_WaitAccessEnable(); + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + RTC_Check(); + + /*-------------------------------------------------------------------------------------------------*/ + /* Important, range of 12-hour PM mode is 21 up to 32 */ + /*-------------------------------------------------------------------------------------------------*/ + if (sPt->u32AmPm == RTC_PM) + { + sPt->u32Hour += 20ul; + } + } + else + { + RTC_WaitAccessEnable(); + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + RTC_Check(); + } + + /* Set Day of the Week */ + RTC_WaitAccessEnable(); + RTC->WEEKDAY = sPt->u32DayOfWeek; + RTC_Check(); + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC Current Date and Time */ + /*-----------------------------------------------------------------------------------------------------*/ + u32RegCAL = ((sPt->u32Year - RTC_YEAR2000) / 10ul) << 20; + u32RegCAL |= (((sPt->u32Year - RTC_YEAR2000) % 10ul) << 16); + u32RegCAL |= ((sPt->u32Month / 10ul) << 12); + u32RegCAL |= ((sPt->u32Month % 10ul) << 8); + u32RegCAL |= ((sPt->u32Day / 10ul) << 4); + u32RegCAL |= (sPt->u32Day % 10ul); + + u32RegTIME = ((sPt->u32Hour / 10ul) << 20); + u32RegTIME |= ((sPt->u32Hour % 10ul) << 16); + u32RegTIME |= ((sPt->u32Minute / 10ul) << 12); + u32RegTIME |= ((sPt->u32Minute % 10ul) << 8); + u32RegTIME |= ((sPt->u32Second / 10ul) << 4); + u32RegTIME |= (sPt->u32Second % 10ul); + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC Calender and Time Loading */ + /*-----------------------------------------------------------------------------------------------------*/ + RTC_WaitAccessEnable(); + RTC->CAL = (uint32_t)u32RegCAL; + RTC_Check(); + RTC_WaitAccessEnable(); + RTC->TIME = (uint32_t)u32RegTIME; + RTC_Check(); + } +} + +/** + * @brief Update RTC Alarm Date and Time + * + * @param[in] sPt 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 *sPt) +{ + uint32_t u32RegCALM, u32RegTALM; + + if (sPt == 0) + { + } + else + { + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC 24/12 hour setting and Day of the Week */ + /*-----------------------------------------------------------------------------------------------------*/ + RTC_WaitAccessEnable(); + if (sPt->u32TimeScale == RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + + /*-------------------------------------------------------------------------------------------------*/ + /* Important, range of 12-hour PM mode is 21 up to 32 */ + /*-------------------------------------------------------------------------------------------------*/ + if (sPt->u32AmPm == RTC_PM) + { + sPt->u32Hour += 20ul; + } + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + RTC_Check(); + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC Alarm Date and Time */ + /*-----------------------------------------------------------------------------------------------------*/ + u32RegCALM = ((sPt->u32Year - RTC_YEAR2000) / 10ul) << 20; + u32RegCALM |= (((sPt->u32Year - RTC_YEAR2000) % 10ul) << 16); + u32RegCALM |= ((sPt->u32Month / 10ul) << 12); + u32RegCALM |= ((sPt->u32Month % 10ul) << 8); + u32RegCALM |= ((sPt->u32Day / 10ul) << 4); + u32RegCALM |= (sPt->u32Day % 10ul); + u32RegCALM |= (sPt->u32DayOfWeek << 24); + + u32RegTALM = ((sPt->u32Hour / 10ul) << 20); + u32RegTALM |= ((sPt->u32Hour % 10ul) << 16); + u32RegTALM |= ((sPt->u32Minute / 10ul) << 12); + u32RegTALM |= ((sPt->u32Minute % 10ul) << 8); + u32RegTALM |= ((sPt->u32Second / 10ul) << 4); + u32RegTALM |= (sPt->u32Second % 10ul); + + RTC_WaitAccessEnable(); + RTC->CALM = (uint32_t)u32RegCALM; + RTC_Check(); + RTC_WaitAccessEnable(); + RTC->TALM = (uint32_t)u32RegTALM; + RTC_Check(); + } +} + +/** + * @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_WaitAccessEnable(); + RTC->WEEKDAY = u32DayOfWeek & RTC_WEEKDAY_WEEKDAY_Msk; + RTC_Check(); + + /* Set RTC Calender Loading */ + RTC_WaitAccessEnable(); + RTC->CAL = (uint32_t)u32RegCAL; + RTC_Check(); +} + +/** + * @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 */ + /*-----------------------------------------------------------------------------------------------------*/ + RTC_WaitAccessEnable(); + if (u32TimeMode == RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + RTC_Check(); + + RTC_WaitAccessEnable(); + RTC->TIME = (uint32_t)u32RegTIME; + RTC_Check(); +} + +/** + * @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. + * @param[in] u32DayOfWeek The day of week + * + * @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 u32DayOfWeek) +{ + 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); + u32RegCALM |= (u32DayOfWeek << 24); + + RTC_WaitAccessEnable(); + + /* Set RTC Alarm Date */ + RTC->CALM = (uint32_t)u32RegCALM; + RTC_Check(); +} + +/** + * @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 == RTC_CLOCK_12) && (u32AmPm == 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 */ + /*-----------------------------------------------------------------------------------------------------*/ + RTC_WaitAccessEnable(); + if (u32TimeMode == RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + RTC_Check(); + + /* Set RTC Alarm Time */ + RTC_WaitAccessEnable(); + RTC->TALM = (uint32_t)u32RegTALM; + RTC_Check(); +} + +/** + * @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_WaitAccessEnable(); + RTC->TICK = (RTC->TICK & ~RTC_TICK_TICK_Msk) | u32TickSelection; + RTC_Check(); +} + +/** + * @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_WaitAccessEnable(); + RTC->INTEN |= u32IntFlagMask; + RTC_Check(); + + if (u32IntFlagMask & RTC_INTEN_ALMIEN_Msk) + { + RTC_WaitAccessEnable(); + RTC->PWRCTL |= RTC_PWRCTL_ALARM_EN_Msk; + RTC_Check(); + } + + if (u32IntFlagMask & RTC_INTEN_RELALMIEN_Msk) + { + RTC_WaitAccessEnable(); + RTC->PWRCTL |= RTC_PWRCTL_REL_ALARM_EN_Msk; + RTC_Check(); + } +} + +/** + * @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_WaitAccessEnable(); + RTC->INTEN &= ~u32IntFlagMask; + RTC_Check(); + RTC_WaitAccessEnable(); + RTC->INTSTS = u32IntFlagMask; + RTC_Check(); +} + +/** + * @brief Wait RTC Access Enable + * + * @param None + * + * @return None + * + * @details This function is used to enable the maximum RTC read/write accessible time. + */ +void RTC_WaitAccessEnable(void) +{ + INT32 volatile i32i; + + RTC_Check(); + + outp32(REG_RTC_RWEN, RTC_WRITE_KEY); + RTC_Check(); + + while (!(inp32(REG_RTC_RWEN) & 0x10000)); +} + +void RTC_Check(void) +{ + uint32_t i = 0; + uint32_t Wait; + + 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) + { + //printf("Time out\n"); + break; + } + } +} + + +/*@}*/ /* end of group RTC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group RTC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_scuart.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_scuart.c new file mode 100644 index 0000000000..ca3e509e4b --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_scuart.c @@ -0,0 +1,242 @@ +/**************************************************************************//** + * @file scuart.c + * @brief NUC980 series Smartcard UART mode (SCUART) driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nu_scuart.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SCUART_Driver SCUART Driver + @{ +*/ + + +/** @addtogroup 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 SCUART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SCUART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sdh.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sdh.c new file mode 100644 index 0000000000..d574ef447b --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sdh.c @@ -0,0 +1,1181 @@ +/**************************************************************************//** + * @file SDH.c + * @brief SDH driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include +#include "nuc980.h" +#include "nu_sdh.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SDH_Driver SDH Driver + @{ +*/ + + +/** @addtogroup 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 SDH_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SDH_Driver */ + +/*@}*/ /* end of group Device_Driver */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_spi.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_spi.c new file mode 100644 index 0000000000..8ffbc32805 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_spi.c @@ -0,0 +1,603 @@ +/**************************************************************************//** + * @file spi.c + * @brief NUC980 series SPI driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nuc980.h" +#include "nu_spi.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 u32RetValue = 0U; + + if (u32DataWidth == 32U) + { + u32DataWidth = 0U; + } + + 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; + + /* Set DIVIDER */ + spi->CLKDIV = (150000000U / u32BusClock) - 1U; + } + 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 = 1, let slave runs at PCLK/2 = 75MHz */ + spi->CLKDIV = 1U; + } + + return u32RetValue; +} + +/** + * @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 */ + } + else + { + /* Reset SPI */ + } +} + +/** + * @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 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) +{ + return 0; +} + +/** + * @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. + */ +uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock) +{ + /* Set DIVIDER */ + if (spi->CTL & SPI_CTL_SLAVE_Msk) //Slave + spi->CLKDIV = 1; + else //Master + spi->CLKDIV = (150000000U / u32BusClock) - 1U; + + return SPI_GetBusClock(spi); +} + + +/** + * @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 = 0U, u32TmpVal; + + u32TmpVal = spi->STATUS & SPI_STATUS_UNITIF_Msk; + /* Check unit transfer interrupt flag */ + if ((u32Mask & SPI_UNIT_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_UNIT_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_SSACTIF_Msk; + /* Check slave selection signal active interrupt flag */ + if ((u32Mask & SPI_SSACT_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_SSACT_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_SSINAIF_Msk; + /* Check slave selection signal inactive interrupt flag */ + if ((u32Mask & SPI_SSINACT_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_SSINACT_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_SLVURIF_Msk; + /* Check slave TX under run interrupt flag */ + if ((u32Mask & SPI_SLVUR_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_SLVUR_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_SLVBEIF_Msk; + /* Check slave bit count error interrupt flag */ + if ((u32Mask & SPI_SLVBE_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_SLVBE_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_TXUFIF_Msk; + /* Check slave TX underflow interrupt flag */ + if ((u32Mask & SPI_TXUF_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_TXUF_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_TXTHIF_Msk; + /* Check TX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_TXTH_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_FIFO_TXTH_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_RXTHIF_Msk; + /* Check RX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTH_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_FIFO_RXTH_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_RXOVIF_Msk; + /* Check RX overrun interrupt flag */ + if ((u32Mask & SPI_FIFO_RXOV_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= SPI_FIFO_RXOV_INT_MASK; + } + + u32TmpVal = spi->STATUS & SPI_STATUS_RXTOIF_Msk; + /* Check RX time-out interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTO_INT_MASK) && (u32TmpVal)) + { + 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 = 0U, u32TmpValue; + + u32TmpValue = spi->STATUS & SPI_STATUS_BUSY_Msk; + /* Check busy status */ + if ((u32Mask & SPI_BUSY_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_BUSY_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_RXEMPTY_Msk; + /* Check RX empty flag */ + if ((u32Mask & SPI_RX_EMPTY_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_RX_EMPTY_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_RXFULL_Msk; + /* Check RX full flag */ + if ((u32Mask & SPI_RX_FULL_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_RX_FULL_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_TXEMPTY_Msk; + /* Check TX empty flag */ + if ((u32Mask & SPI_TX_EMPTY_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_TX_EMPTY_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_TXFULL_Msk; + /* Check TX full flag */ + if ((u32Mask & SPI_TX_FULL_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_TX_FULL_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_TXRXRST_Msk; + /* Check TX/RX reset flag */ + if ((u32Mask & SPI_TXRX_RESET_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_TXRX_RESET_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_SPIENSTS_Msk; + /* Check SPIEN flag */ + if ((u32Mask & SPI_SPIEN_STS_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_SPIEN_STS_MASK; + } + + u32TmpValue = spi->STATUS & SPI_STATUS_SSLINE_Msk; + /* Check SPIx_SS line status */ + if ((u32Mask & SPI_SSLINE_STS_MASK) && (u32TmpValue)) + { + u32Flag |= SPI_SSLINE_STS_MASK; + } + + return u32Flag; +} + +/*@}*/ /* end of group SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sys.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sys.c new file mode 100644 index 0000000000..97259b1c8c --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_sys.c @@ -0,0 +1,723 @@ +/**************************************************************************//** + * @file sys.c + * @brief SYS driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include +#include "nuc980.h" +#include "nu_sys.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SYS_Driver SYS Driver + @{ +*/ + +/** @addtogroup SYS_EXPORTED_CONSTANTS SYS Exported Constants + @{ +*/ + +/// @cond HIDDEN_SYMBOLS + +#define SYS_MIN_INT_SOURCE 1 +#define SYS_MAX_INT_SOURCE 63 +#define SYS_NUM_OF_AICREG 16 + +/* Global variables */ +UINT32 volatile _sys_bIsAICInitial = 0x0; + +/* declaration the function prototype */ +void SYS_IRQ_Shell(void); +void SYS_FIQ_Shell(void); + +/* Interrupt Handler Table */ +//typedef void (*sys_pvFunPtr)(); /* function pointer */ +sys_pvFunPtr sysIrqHandlerTable[] = { 0, /* 0 */ + SYS_IRQ_Shell, /* 1 */ + SYS_IRQ_Shell, /* 2 */ + SYS_IRQ_Shell, /* 3 */ + SYS_IRQ_Shell, /* 4 */ + SYS_IRQ_Shell, /* 5 */ + SYS_IRQ_Shell, /* 6 */ + SYS_IRQ_Shell, /* 7 */ + SYS_IRQ_Shell, /* 8 */ + SYS_IRQ_Shell, /* 9 */ + SYS_IRQ_Shell, /* 10 */ + SYS_IRQ_Shell, /* 11 */ + SYS_IRQ_Shell, /* 12 */ + SYS_IRQ_Shell, /* 13 */ + SYS_IRQ_Shell, /* 14 */ + SYS_IRQ_Shell, /* 15 */ + SYS_IRQ_Shell, /* 16 */ + SYS_IRQ_Shell, /* 17 */ + SYS_IRQ_Shell, /* 18 */ + SYS_IRQ_Shell, /* 19 */ + SYS_IRQ_Shell, /* 20 */ + SYS_IRQ_Shell, /* 21 */ + SYS_IRQ_Shell, /* 22 */ + SYS_IRQ_Shell, /* 23 */ + SYS_IRQ_Shell, /* 24 */ + SYS_IRQ_Shell, /* 25 */ + SYS_IRQ_Shell, /* 26 */ + SYS_IRQ_Shell, /* 27 */ + SYS_IRQ_Shell, /* 28 */ + SYS_IRQ_Shell, /* 29 */ + SYS_IRQ_Shell, /* 30 */ + SYS_IRQ_Shell, /* 31 */ + SYS_IRQ_Shell, /* 32 */ + SYS_IRQ_Shell, /* 33 */ + SYS_IRQ_Shell, /* 34 */ + SYS_IRQ_Shell, /* 35 */ + SYS_IRQ_Shell, /* 36 */ + SYS_IRQ_Shell, /* 37 */ + SYS_IRQ_Shell, /* 38 */ + SYS_IRQ_Shell, /* 39 */ + SYS_IRQ_Shell, /* 40 */ + SYS_IRQ_Shell, /* 41 */ + SYS_IRQ_Shell, /* 42 */ + SYS_IRQ_Shell, /* 43 */ + SYS_IRQ_Shell, /* 44 */ + SYS_IRQ_Shell, /* 45 */ + SYS_IRQ_Shell, /* 46 */ + SYS_IRQ_Shell, /* 47 */ + SYS_IRQ_Shell, /* 48 */ + SYS_IRQ_Shell, /* 49 */ + SYS_IRQ_Shell, /* 50 */ + SYS_IRQ_Shell, /* 51 */ + SYS_IRQ_Shell, /* 52 */ + SYS_IRQ_Shell, /* 53 */ + SYS_IRQ_Shell, /* 54 */ + SYS_IRQ_Shell, /* 55 */ + SYS_IRQ_Shell, /* 56 */ + SYS_IRQ_Shell, /* 57 */ + SYS_IRQ_Shell, /* 58 */ + SYS_IRQ_Shell, /* 59 */ + SYS_IRQ_Shell, /* 60 */ + SYS_IRQ_Shell, /* 61 */ + SYS_IRQ_Shell, /* 62 */ + SYS_IRQ_Shell /* 63 */ + }; + +sys_pvFunPtr sysFiqHandlerTable[] = { 0, + SYS_FIQ_Shell, /* 1 */ + SYS_FIQ_Shell, /* 2 */ + SYS_FIQ_Shell, /* 3 */ + SYS_FIQ_Shell, /* 4 */ + SYS_FIQ_Shell, /* 5 */ + SYS_FIQ_Shell, /* 6 */ + SYS_FIQ_Shell, /* 7 */ + SYS_FIQ_Shell, /* 8 */ + SYS_FIQ_Shell, /* 9 */ + SYS_FIQ_Shell, /* 10 */ + SYS_FIQ_Shell, /* 11 */ + SYS_FIQ_Shell, /* 12 */ + SYS_FIQ_Shell, /* 13 */ + SYS_FIQ_Shell, /* 14 */ + SYS_FIQ_Shell, /* 15 */ + SYS_FIQ_Shell, /* 16 */ + SYS_FIQ_Shell, /* 17 */ + SYS_FIQ_Shell, /* 18 */ + SYS_FIQ_Shell, /* 19 */ + SYS_FIQ_Shell, /* 20 */ + SYS_FIQ_Shell, /* 21 */ + SYS_FIQ_Shell, /* 22 */ + SYS_FIQ_Shell, /* 23 */ + SYS_FIQ_Shell, /* 24 */ + SYS_FIQ_Shell, /* 25 */ + SYS_FIQ_Shell, /* 26 */ + SYS_FIQ_Shell, /* 27 */ + SYS_FIQ_Shell, /* 28 */ + SYS_FIQ_Shell, /* 29 */ + SYS_FIQ_Shell, /* 30 */ + SYS_FIQ_Shell, /* 31 */ + SYS_FIQ_Shell, /* 32 */ + SYS_FIQ_Shell, /* 33 */ + SYS_FIQ_Shell, /* 34 */ + SYS_FIQ_Shell, /* 35 */ + SYS_FIQ_Shell, /* 36 */ + SYS_FIQ_Shell, /* 37 */ + SYS_FIQ_Shell, /* 38 */ + SYS_FIQ_Shell, /* 39 */ + SYS_FIQ_Shell, /* 40 */ + SYS_FIQ_Shell, /* 41 */ + SYS_FIQ_Shell, /* 42 */ + SYS_FIQ_Shell, /* 43 */ + SYS_FIQ_Shell, /* 44 */ + SYS_FIQ_Shell, /* 45 */ + SYS_FIQ_Shell, /* 46 */ + SYS_FIQ_Shell, /* 47 */ + SYS_FIQ_Shell, /* 48 */ + SYS_FIQ_Shell, /* 49 */ + SYS_FIQ_Shell, /* 50 */ + SYS_FIQ_Shell, /* 51 */ + SYS_FIQ_Shell, /* 52 */ + SYS_FIQ_Shell, /* 53 */ + SYS_FIQ_Shell, /* 54 */ + SYS_FIQ_Shell, /* 55 */ + SYS_FIQ_Shell, /* 56 */ + SYS_FIQ_Shell, /* 57 */ + SYS_FIQ_Shell, /* 58 */ + SYS_FIQ_Shell, /* 59 */ + SYS_FIQ_Shell, /* 60 */ + SYS_FIQ_Shell, /* 61 */ + SYS_FIQ_Shell, /* 62 */ + SYS_FIQ_Shell /* 63 */ + }; + +/* Interrupt Handler */ +#if defined (__GNUC__) && !(__CC_ARM) + static void __attribute__((interrupt("IRQ"))) sysIrqHandler(void) +#else + __irq void sysIrqHandler() +#endif +{ + UINT32 volatile num; + + num = inpw(REG_AIC_IRQNUM); + if (num != 0) + (*sysIrqHandlerTable[num])(); + outpw(REG_AIC_EOIS, 1); +} + +#if defined (__GNUC__) && !(__CC_ARM) + static void __attribute__((interrupt("FIQ"))) sysFiqHandler(void) +#else + __irq void sysFiqHandler() +#endif +{ + UINT32 volatile num; + + num = inpw(REG_AIC_FIQNUM); + if (num != 0) + (*sysIrqHandlerTable[num])(); + outpw(REG_AIC_EOFS, 1); +} + +void SYS_IRQ_Shell(void) +{ + printf("ISR not found! ISNR=%d\n", inpw(REG_AIC_IRQNUM)); +} + +void SYS_FIQ_Shell(void) +{ + printf("ISR not found! ISNR=%d\n", inpw(REG_AIC_FIQNUM)); +} + +void sysInitializeAIC() +{ +#if defined (__GNUC__) && !(__CC_ARM) + *(unsigned int volatile *)0x34 = (unsigned int volatile)sysIrqHandler; + + *(unsigned int volatile *)0x38 = (unsigned int volatile)sysFiqHandler; +#else + *(unsigned int volatile *)0x38 = (unsigned int)sysIrqHandler; + + *(unsigned int volatile *)0x3C = (unsigned int)sysFiqHandler; +#endif +} +/// @endcond HIDDEN_SYMBOLS + +/*@}*/ /* end of group SYS_EXPORTED_CONSTANTS */ + +/** @addtogroup SYS_EXPORTED_FUNCTIONS SYS Exported Functions + @{ +*/ + +/// @cond 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 Fail; + + if (eIntNo < 32) + outpw(REG_AIC_INTDIS0, (1 << eIntNo)); + else + outpw(REG_AIC_INTDIS1, (1 << (eIntNo - 32))); + + return Successful; +} + + +/** + * @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 Fail; + + if (eIntNo < 32) + outpw(REG_AIC_INTEN0, (1 << eIntNo)); + else + outpw(REG_AIC_INTEN1, (1 << (eIntNo - 32))); + + return Successful; +} + + +/** + * @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_SRCCTL0 + ((eIntNo / 4) * 4); + shift = (eIntNo % 4) * 8; + nIntTypeLevel &= 0xff; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x0f << 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_INTEN0, 0xFFFFFFFF); + outpw(REG_AIC_INTEN1, 0xFFFFFFFF); + break; + + case DISABLE_ALL_INTERRUPTS: + outpw(REG_AIC_INTDIS0, 0xFFFFFFFF); + outpw(REG_AIC_INTDIS1, 0xFFFFFFFF); + break; + + default: + ; + } + return Successful; +} + + +/** + * @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_SRCCTL0 + ((eIntNo / 4) * 4); + shift = (eIntNo % 4) * 8; + uIntLevel &= 0x7; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x07 << shift)) | (uIntLevel << 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__ __volatile__ + ( + "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__ __volatile__ + ( + "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_INTMSK0)); +} + + +UINT32 sysGetInterruptEnableStatusH(void) +{ + return (inpw(REG_AIC_INTMSK1)); +} +/// @endcond HIDDEN_SYMBOLS + +/// @cond HIDDEN_SYMBOLS +BOOL sysGetIBitState() +{ + INT32 temp; +#if defined (__GNUC__) && !(__CC_ARM) + __asm__ __volatile__ + ( + "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, divN, reg; + + 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; + } + divN = ((reg & 0x100) >> 8) + 1; + return (src / divN); + } + + case SYS_HCLK: + { + 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; + } + divN = ((reg & 0x100) >> 8) + 1; + return (src / divN / 2); + } + + case SYS_PCLK01: + { + 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; + } + divN = ((reg & 0x100) >> 8) + 1; + return (src / divN / 2); + } + + 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; + } + divN = ((reg & 0x10000) >> 16) + 1; + return (src / divN); + } + + case SYS_PCLK2: + { + 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; + } + divN = ((reg & 0x100) >> 8) + 1; + return (src / divN / 2 / 2); + } + default: + ; + } + return 0; //write me!! +} + +INT32 sysGetSdramSizebyMB(void) +{ + unsigned int volatile reg, totalsize = 0; + + reg = inpw(SDIC_BA + 0x10) & 0x07; + switch (reg) + { + case 1: + totalsize += 2; + break; + + case 2: + totalsize += 4; + break; + + case 3: + totalsize += 8; + break; + + case 4: + totalsize += 16; + break; + + case 5: + totalsize += 32; + break; + + case 6: + totalsize += 64; + break; + + case 7: + totalsize += 128; + break; + } + if ((inpw(SDIC_BA + 0x14) & (0xFF << 21)) != 0) + totalsize += totalsize; + + return totalsize; +} + +/*@}*/ /* 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/nuc980/Driver/Source/nu_uart.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_uart.c new file mode 100644 index 0000000000..fb373792ba --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_uart.c @@ -0,0 +1,776 @@ +/**************************************************************************//** + * @file uart.c + * @version V3.00 + * @brief NUC980 series UART driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include "nu_uart.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_LININT_Msk : LIN bus 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_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; + } + else + { + } + + 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; + } + + if (u32InterruptFlag & UART_INTSTS_LININT_Msk) /* Clear LIN Bus Interrupt */ + { + uart->INTSTS = UART_INTSTS_LINIF_Msk; + uart->LINSTS = UART_LINSTS_BITEF_Msk | UART_LINSTS_BRKDETF_Msk | + UART_LINSTS_SLVSYNCF_Msk | UART_LINSTS_SLVIDPEF_Msk | + UART_LINSTS_SLVHEF_Msk | UART_LINSTS_SLVHDETF_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_INTEN_WKIEN_Msk : Wake-up interrupt + * - \ref UART_INTEN_LINIEN_Msk : Lin bus 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_INTEN_WKIEN_Msk : Wake-up interrupt + * - \ref UART_INTEN_LINIEN_Msk : Lin bus 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[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; + } + + /* 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); + } + } +} + + +/** + * @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; + } + else + { + } + } + + 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_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; + } + + /* 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; +} + + +/** + * @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[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; + } + + /* 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 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 RS585 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 Select and configure LIN function + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32Mode The LIN direction : + * - \ref UART_ALTCTL_LINTXEN_Msk + * - \ref UART_ALTCTL_LINRXEN_Msk + * @param[in] u32BreakLength The break field length. + * + * @return None + * + * @details The function is used to set LIN relative setting. + */ +void UART_SelectLINMode(UART_T *uart, uint32_t u32Mode, uint32_t u32BreakLength) +{ + /* Select LIN function mode */ + uart->FUNCSEL = UART_FUNCSEL_LIN; + + /* Select LIN function setting : Tx enable, Rx enable and break field length */ + uart->ALTCTL &= ~(UART_ALTCTL_LINTXEN_Msk | UART_ALTCTL_LINRXEN_Msk | UART_ALTCTL_BRKFL_Msk); + uart->ALTCTL |= (u32Mode | (u32BreakLength << UART_ALTCTL_BRKFL_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_TXEMPTYF_Msk) == 0ul) /* Wait Tx empty and Time-out manner */ + { + u32delayno++; + if (u32delayno >= 0x40000000ul) + { + u32Exit = 1ul; + break; + } + else + { + } + } + + if (u32Exit == 1ul) + { + break; + } + else + { + uart->DAT = pu8TxBuf[u32Count]; /* Send UART Data from buffer */ + } + } + + return u32Count; + +} + +/** + * @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. + */ +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. + */ +void UART_SET_RTS(UART_T *uart) +{ + uart->MODEM |= UART_MODEM_RTSACTLV_Msk | UART_MODEM_RTS_Msk; +} + +/*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group UART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ + + + diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_usbd.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_usbd.c new file mode 100644 index 0000000000..29c7946ce5 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_usbd.c @@ -0,0 +1,679 @@ +/**************************************************************************//** + * @file usbd.c + * @version V1.00 + * $Revision: 2 $ + * $Date: 18/08/05 2:58p $ + * @brief NuMicro ARM9 USBD driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nuc980.h" +#include "nu_usbd.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USBD_Driver USBD Driver + @{ +*/ + +/** @addtogroup USBD_EXPORTED_CONSTANTS USBD Exported Constants + @{ +*/ +/*--------------------------------------------------------------------------*/ +/// @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 = NULL; +CLASS_REQ g_usbd_pfnClassRequest = NULL; +SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL; +uint32_t g_u32EpStallLock = 0; /*!< Bit map flag to lock specified EP when SET_FEATURE */ +uint8_t volatile g_usbd_RemoteWakeupEn = 0ul; + +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) +{ + int volatile i; + /* Select Vbus detect pin -> GPE11 */ + outpw(REG_SYS_GPE_MFPH, (inpw(REG_SYS_GPE_MFPH) & ~0xf000) | 0x1000); + /* Enable USB device clock */ + outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | 0x80000); + outpw(REG_SYS_AHBIPRST, inpw(REG_SYS_AHBIPRST) | 0x80000); + outpw(REG_SYS_AHBIPRST, inpw(REG_SYS_AHBIPRST) & ~0x80000); + for (i = 0; i < 1000; i++); + + 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; + int val = 0; + + u32Len = gUsbCmd.wLength; + g_usbd_CtrlZero = 0; + USBD->CEPCTL |= USBD_CEPCTL_FLUSH_Msk; + + 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; + if ((USBD->OPER & 0x04ul) == 0x04ul) + { + u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8); + + if (u32Len > u32TotalLen) + { + u32Len = u32TotalLen; + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0) + { + g_usbd_CtrlZero = 1; + } + } + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len); + } + else + { + u32TotalLen = g_usbd_sInfo->gu8FullConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8FullConfigDesc[2] + (u32TotalLen << 8); + + if (u32Len > u32TotalLen) + { + u32Len = u32TotalLen; + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul) + { + g_usbd_CtrlZero = (uint8_t)1ul; + } + } + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8FullConfigDesc, 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; + if ((USBD->OPER & 0x04ul) == 0x04ul) + { + u32TotalLen = g_usbd_sInfo->gu8HSOtherConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8HSOtherConfigDesc[2] + (u32TotalLen << 8); + + if (u32Len > u32TotalLen) + { + u32Len = u32TotalLen; + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0) + { + g_usbd_CtrlZero = 1; + } + } + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HSOtherConfigDesc, u32Len); + } + else + { + u32TotalLen = g_usbd_sInfo->gu8FSOtherConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8FSOtherConfigDesc[2] + (u32TotalLen << 8); + + if (u32Len > u32TotalLen) + { + u32Len = u32TotalLen; + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul) + { + g_usbd_CtrlZero = (uint8_t)1ul; + } + } + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8FSOtherConfigDesc, 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: + { + if ((gUsbCmd.wValue & 0xfful) < 8ul) + { + if (u32Len > g_usbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful][0]) + { + u32Len = g_usbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful][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); + val = 1; + } + break; + } + default: + /* Not support. Reply STALL. */ + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + val = 1; + break; + } + return val; +} + + +/** + * @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) + { + g_usbd_buf[0] = (uint8_t)0ul; /* bus-Powered */ + if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul) + { + g_usbd_buf[0] = (uint8_t)1ul; /* Self-Powered */ + } + + if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x20ul) == 0x20ul) + g_usbd_buf[0] |= (uint8_t)(g_usbd_RemoteWakeupEn << 1); // Remote wake up + } + // 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 USBD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USBD_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wdt.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wdt.c new file mode 100644 index 0000000000..2db0cdc96e --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wdt.c @@ -0,0 +1,67 @@ +/**************************************************************************//** + * @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 + * * \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 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/nuc980/Driver/Source/nu_wwdt.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wwdt.c new file mode 100644 index 0000000000..1488a3036f --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_wwdt.c @@ -0,0 +1,67 @@ +/**************************************************************************//** + * @file wwdt.c + * @brief NUC980 WWDT driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nu_wwdt.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup WWDT_Driver WWDT Driver + @{ +*/ + + +/** @addtogroup 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 WWDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group WWDT_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + diff --git a/bsp/nuvoton/libraries/nuc980/README.md b/bsp/nuvoton/libraries/nuc980/README.md new file mode 100644 index 0000000000..75766d2d7c --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/README.md @@ -0,0 +1,28 @@ +# NUC980 Series + +## Supported drivers + +| Peripheral | rt_device_class_type | Device name | +| ------ | ---- | :------: | +| ADC | RT_Device_Class_Miscellaneous (ADC) | ***adc*** | +| CAN | RT_Device_Class_CAN | ***can[0-3]*** | +| CRYPTO | RT_Device_Class_Miscellaneous (HW Crypto) | ***hwcryto*** | +| EBI | N/A | ***N/A*** | +| EMAC | RT_Device_Class_NetIf | ***e[0-1]*** | +| GPIO | RT_Device_Class_Miscellaneous (Pin) | ***gpio*** | +| I2C | RT_Device_Class_I2CBUS | ***i2c[0-3]*** | +| PDMA | N/A | ***N/A*** | +| QSPI | RT_Device_Class_SPIBUS | ***qspi[0]*** | +| RTC | RT_Device_Class_RTC | ***rtc*** | +| PWM | RT_Device_Class_Miscellaneous (PWM) | ***pwm[0-1]*** | +| SC (UART function) | RT_Device_Class_Char | ***scuart[0-1]*** | +| SDH | RT_Device_Class_Block | ***sdh[0-1]*** | +| SPI | RT_Device_Class_SPIBUS | ***spi[0-1]*** | +| TIMER | RT_Device_Class_Timer | ***timer[0-5]*** | +| UART | RT_Device_Class_Char | ***uart[0-9]*** | +| WDT | RT_Device_Class_Miscellaneous (Watchdog) | ***wdt*** | + +## Resources +* [Download NUC980 TRM][1] + + [1]: https://www.nuvoton.com/resource-download.jsp?tp_GUID=DA05-M480 diff --git a/bsp/nuvoton/libraries/nuc980/SConscript b/bsp/nuvoton/libraries/nuc980/SConscript new file mode 100644 index 0000000000..4c815c49b8 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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/bsp/nuvoton/libraries/nuc980/Script/NUC980xx41.ini b/bsp/nuvoton/libraries/nuc980/Script/NUC980xx41.ini new file mode 100644 index 0000000000..b9d1147337 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Script/NUC980xx41.ini @@ -0,0 +1,24 @@ +E INT 0xB0000264 = 0xC0000018 +E INT 0xB0000220 = 0x01000018 +E INT 0xB0002028 = 0x53DCD84A +E INT 0xB0002008 = 0x00008014 +E INT 0xB0002000 = 0x0003047E +E INT 0xB0002004 = 0x00000021 +E INT 0xB0002004 = 0x00000023 +E INT 0xB0002004 = 0x00000027 +E INT 0xB0002020 = 0x00000000 +E INT 0xB0002024 = 0x00000000 +E INT 0xB000201C = 0x00004000 +E INT 0xB0002018 = 0x00000332 +E INT 0xB0002010 = 0x00000004 +E INT 0xB0002004 = 0x00000027 +E INT 0xB0002004 = 0x0000002B +E INT 0xB0002004 = 0x0000002B +E INT 0xB0002004 = 0x0000002B +E INT 0xB0002018 = 0x00000232 +E INT 0xB000201C = 0x00004781 +E INT 0xB000201C = 0x00004401 +E INT 0xB0002004 = 0x00000020 +E INT 0xB0002034 = 0x00888828 +LOAD %L INCREMENTAL +$ = 0x8000 \ No newline at end of file diff --git a/bsp/nuvoton/libraries/nuc980/Script/NUC980xx61.ini b/bsp/nuvoton/libraries/nuc980/Script/NUC980xx61.ini new file mode 100644 index 0000000000..dbc8b7e518 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Script/NUC980xx61.ini @@ -0,0 +1,24 @@ +E INT 0xB0000264 = 0xC0000018 +E INT 0xB0000220 = 0x01000018 +E INT 0xB0002028 = 0x53DCD84A +E INT 0xB0002008 = 0x00008014 +E INT 0xB0002000 = 0x0003047E +E INT 0xB0002004 = 0x00000021 +E INT 0xB0002004 = 0x00000023 +E INT 0xB0002004 = 0x00000027 +E INT 0xB0002020 = 0x00000000 +E INT 0xB0002024 = 0x00000000 +E INT 0xB000201C = 0x00004000 +E INT 0xB0002018 = 0x00000332 +E INT 0xB0002010 = 0x00000006 +E INT 0xB0002004 = 0x00000027 +E INT 0xB0002004 = 0x0000002B +E INT 0xB0002004 = 0x0000002B +E INT 0xB0002004 = 0x0000002B +E INT 0xB0002018 = 0x00000232 +E INT 0xB000201C = 0x00004781 +E INT 0xB000201C = 0x00004401 +E INT 0xB0002004 = 0x00000020 +E INT 0xB0002034 = 0x00888828 +LOAD %L INCREMENTAL +$ = 0x00000000 \ No newline at end of file diff --git a/bsp/nuvoton/libraries/nuc980/Script/NUC980xx71.ini b/bsp/nuvoton/libraries/nuc980/Script/NUC980xx71.ini new file mode 100644 index 0000000000..1ff516d8eb --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/Script/NUC980xx71.ini @@ -0,0 +1,26 @@ +E INT 0xB0000264 = 0xC0000018 +E INT 0xB0000220 = 0x00000018 +E INT 0xB0002028 = 0x53EB384A +E INT 0xB0002008 = 0x00008014 +E INT 0xB0002000 = 0x00010476 +E INT 0xB0002004 = 0x00000001 +E INT 0xB0002004 = 0x00000003 +E INT 0xB0002004 = 0x00000007 +E INT 0xB0002020 = 0x00000000 +E INT 0xB0002024 = 0x00000000 +E INT 0xB000201C = 0x00004001 +E INT 0xB0002018 = 0x00000332 +E INT 0xB0002010 = 0x00000007 +E INT 0xB0002004 = 0x00000007 +E INT 0xB0002004 = 0x0000000B +E INT 0xB0002004 = 0x0000000B +E INT 0xB0002004 = 0x0000000B +E INT 0xB0002018 = 0x00000232 +E INT 0xB000201C = 0x000027C5 +E INT 0xB000201C = 0x00002445 +E INT 0xB0002008 = 0x000080C0 +E INT 0xB0002004 = 0x00000020 +E INT 0xB0002030 = 0x00001010 +E INT 0xB0002034 = 0x00CCCC0A +LOAD %L INCREMENTAL +$ = 0x8000 \ No newline at end of file diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig new file mode 100644 index 0000000000..eb1726a28d --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig @@ -0,0 +1,656 @@ +config SOC_SERIES_NUC980 + 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 + + 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_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" + + config NU_EMAC_PDMA_MEMCOPY + bool "Use PDMA for data transferring" + select BSP_USING_PDMA + default y + + config NU_EMAC_PDMA_MEMCOPY_THRESHOLD + int "Min threshold to do PDMA memcpy" + range 32 1500 + default 128 + depends on NU_EMAC_PDMA_MEMCOPY + 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 + + menuconfig BSP_USING_TMR + bool "Enable Timer Controller(TIMER)" + + if BSP_USING_TMR + + config BSP_USING_TIMER + bool + + config BSP_USING_TPWM + 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_TPWM0 + select BSP_USING_TPWM + select RT_USING_PWM + bool "TIMER PWM" + help + Choose this option if you need PWM 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_TPWM1 + select BSP_USING_TPWM + select RT_USING_PWM + bool "TIMER PWM" + help + Choose this option if you need PWM 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_TPWM2 + select BSP_USING_TPWM + select RT_USING_PWM + bool "TIMER PWM" + help + Choose this option if you need PWM 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 + + 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_TPWM3 + select BSP_USING_TPWM + select RT_USING_PWM + bool "TIMER PWM" + help + Choose this option if you need PWM 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 + + config BSP_USING_TMR4 + bool "Enable TIMER4" + depends on BSP_USING_TMR + + if BSP_USING_TMR4 + choice + prompt "Select TIMER4 function mode" + + config BSP_USING_TIMER4 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TPWM4 + select BSP_USING_TPWM + select RT_USING_PWM + bool "TIMER PWM" + help + Choose this option if you need PWM function mode. + + config BSP_USING_TIMER4_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 + + 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 + + config BSP_USING_UART8 + bool "Enable UART8" + + config BSP_USING_UART8_TX_DMA + bool "Enable UART8 TX DMA" + depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA + + config BSP_USING_UART8_RX_DMA + bool "Enable UART8 RX DMA" + depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA + + config BSP_USING_UART9 + bool "Enable UART9" + + config BSP_USING_UART9_TX_DMA + bool "Enable UART9 TX DMA" + depends on BSP_USING_UART9 && RT_SERIAL_USING_DMA + + config BSP_USING_UART9_RX_DMA + bool "Enable UART9 RX DMA" + depends on BSP_USING_UART9 && 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" + + config BSP_USING_I2C2 + bool "Enable I2C2" + + config BSP_USING_I2C3 + bool "Enable I2C3" + + 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_USING_PDMA + bool "Using PDMA" + select BSP_USING_PDMA + + 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" + + config BSP_USING_CAN2 + bool "Enable CAN2" + + config BSP_USING_CAN3 + bool "Enable CAN3" + 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. + + config BSP_USING_PWM1 + select RT_USING_PWM + bool "Enable PWM1" + help + Choose this option if you need PWM function mode. + 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 + + 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. + 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 + + choice + prompt "Select SPI1 function mode" + config BSP_USING_SPI1_NONE + bool "NONE" + help + Choose this option if you need not SPI1. + + config BSP_USING_SPI1 + bool "Enable SPI1" + help + Choose this option if you need SPI function mode. + endchoice + + if BSP_USING_SPI1 + config BSP_USING_SPI1_PDMA + bool "Enable PDMA for SPI1" + select BSP_USING_SPI_PDMA + depends on BSP_USING_SPI1 + endif + + 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_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_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" + + config BSP_USING_SCUART2 + bool "Enable SCUART2" + 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_USBD + bool "Enable Full-Speed USB Device Controller(USBD)" + select RT_USING_USB_DEVICE + + config BSP_USING_HSUSBD + bool "Enable High-Speed USB Device Controller(HSUSBD)" + select RT_USING_USB_DEVICE + + config BSP_USING_USBH + bool "Enable Full-Speed USB Host Controller(USBH)" + select RT_USING_USB_HOST + select RT_USBH_MSTORAGE + + config BSP_USING_HSUSBH + bool "Enable High-Speed USB Host Controller(HSUSBH)" + select RT_USING_USB_HOST + select RT_USBH_MSTORAGE + + config BSP_USING_HSOTG + bool "Enable High-Speed USB On-The-Go(HSOTG)" + select BSP_USING_HSUSBH + select BSP_USING_HSUSBD diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/SConscript b/bsp/nuvoton/libraries/nuc980/rtt_port/SConscript new file mode 100644 index 0000000000..d9e3c9961f --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/SConscript @@ -0,0 +1,35 @@ +# 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 +if GetDepend('BOARD_USING_HSUSBD') and ( GetDepend('BSP_USING_USBD') or GetDepend('BSP_USING_HSUSBH') or GetDepend('BSP_USING_HSOTG') ): + print 'Sorry, wrong selection.' + print '[Hint] You already select BOARD_USING_HSUSBD. Please de-select BSP_USING_USBD, BSP_USING_HSUSBH and BSP_USING_HSOTG options.' + sys.exit(1) +elif GetDepend('BOARD_USING_HSUSBD_USBH') and ( GetDepend('BSP_USING_USBD') or GetDepend('BSP_USING_HSUSBH') or GetDepend('BSP_USING_HSOTG') ): + print 'Sorry, wrong selection.' + print '[Hint] You already select BOARD_USING_HSUSBD_USBH. Please de-select BSP_USING_USBD, BSP_USING_HSUSBH and BSP_USING_HSOTG options.' + sys.exit(1) +elif GetDepend('BOARD_USING_HSUSBH') and ( GetDepend('BSP_USING_USBH') or GetDepend('BSP_USING_HSUSBD') or GetDepend('BSP_USING_HSOTG') ): + print 'Sorry, wrong selection.' + print '[Hint] You already select BOARD_USING_HSUSBH. Please de-select BSP_USING_USBH, BSP_USING_HSUSBD and BSP_USING_HSOTG options.' + sys.exit(1) +elif GetDepend('BOARD_USING_HSUSBH_USBD') and ( GetDepend('BSP_USING_USBH') or GetDepend('BSP_USING_HSUSBD') or GetDepend('BSP_USING_HSOTG') ): + print 'Sorry, wrong selection.' + print '[Hint] You already select BOARD_USING_HSUSBH_USBD. Please de-select BSP_USING_USBH, BSP_USING_HSUSBD and BSP_USING_HSOTG options.' + sys.exit(1) +elif GetDepend('BOARD_USING_HSOTG') and ( GetDepend('BSP_USING_USBD') or GetDepend('BSP_USING_USBH') ): + print 'Sorry, wrong selection.' + print '[Hint] You already select BOARD_USING_HSOTG. Please de-select BSP_USING_USBD and BSP_USING_USBH options.' + sys.exit(1) +else: + group = DefineGroup('nuc980_rttport', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c new file mode 100644 index 0000000000..a35fe81c8b --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c @@ -0,0 +1,286 @@ +/**************************************************************************//** +* @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 +#include + +/* Private define ---------------------------------------------------------------*/ + +/* 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; +}; +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_adc_convert(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 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) +{ + uint32_t isr, conf; + nu_adc_t psNuAdc = (nu_adc_t)param; + + conf = inpw(REG_ADC_CONF); + isr = inpw(REG_ADC_ISR); + + if ((isr & ADC_ISR_NACF) && (conf & ADC_CONF_NACEN)) + { + outpw(REG_ADC_ISR, ADC_ISR_NACF); + } + + if (isr & ADC_ISR_MF) + { + rt_err_t result; + outpw(REG_ADC_ISR, ADC_ISR_MF); + result = rt_sem_release(psNuAdc->m_psSem); + RT_ASSERT(result == RT_EOK); + } +} + +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; +} + +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; + + 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 */ + *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF; + } + break; + 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 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 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; +} + +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) ; +} + +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); + + return (int)result; +} +INIT_BOARD_EXPORT(rt_hw_adc_init); + +#endif //#if defined(BSP_USING_EADC) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c new file mode 100644 index 0000000000..d74148a441 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c @@ -0,0 +1,554 @@ +/**************************************************************************//** +* +* @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 +#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 +#if defined(BSP_USING_CAN2) + CAN2_IDX, +#endif +#if defined(BSP_USING_CAN3) + CAN3_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 +#if defined(BSP_USING_CAN2) + { + .name = "can2", + .base = CAN2, + .irqn = IRQ_CAN2, + .rstidx = CAN2RST, + .clkidx = CAN2CKEN, + }, +#endif +#if defined(BSP_USING_CAN3) + { + .name = "can3", + .base = CAN3, + .irqn = IRQ_CAN3, + .rstidx = CAN3RST, + .clkidx = CAN3CKEN, + }, +#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 = base->IIDR; + + if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + { + /**************************/ + /* Status Change interrupt*/ + /**************************/ + if (base->STATUS & CAN_STATUS_RXOK_Msk) + { + +#ifndef RT_CAN_USING_HDR + /* Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); +#endif + base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ + rt_kprintf("%s: RX\n", psNuCAN->name) ; + } + + if (base->STATUS & CAN_STATUS_TXOK_Msk) + { + +#ifndef RT_CAN_USING_HDR + /* Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); +#endif + base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ + rt_kprintf("%s: TX\n", psNuCAN->name) ; + } + + /**************************/ + /* 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); + } + } +#ifdef RT_CAN_USING_HDR + /*Number of Message Object which caused the interrupt*/ + else if (u32IIDRstatus != 0 && u32IIDRstatus <= 32) + { + rt_kprintf("=> Interrupt Pointer = %d\n", base->IIDR - 1); + /*Message RAM 0~15 for CAN Tx using*/ + if (u32IIDRstatus < 16) + { + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } + else /*Message RAM 16~31 for CAN Rx using*/ + { + rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | (((base->IIDR) - 1) << 8))); + } + CAN_CLR_INT_PENDING_BIT(base, ((base->IIDR) - 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 */ + CAN_Receive(base, boxno, &tMsg); + +#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/nuc980/rtt_port/drv_common.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c new file mode 100644 index 0000000000..f13b271ea9 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c @@ -0,0 +1,81 @@ +/**************************************************************************//** +* +* @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 + +void nu_clock_base_dump(void) +{ + rt_kprintf("SYS_UPLL = %d\n", sysGetClock(SYS_UPLL)); + rt_kprintf("SYS_APLL = %d\n", sysGetClock(SYS_APLL)); + rt_kprintf("SYS_SYSTEM = %d\n", sysGetClock(SYS_SYSTEM)); + rt_kprintf("SYS_HCLK = %d\n", sysGetClock(SYS_HCLK)); + rt_kprintf("SYS_PCLK01 = %d\n", sysGetClock(SYS_PCLK01)); + rt_kprintf("SYS_PCLK2 = %d\n", sysGetClock(SYS_PCLK2)); + rt_kprintf("SYS_CPU = %d\n", sysGetClock(SYS_CPU)); +} + +/** + * 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])); +#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 + + nu_clock_base_dump(); + rt_kprintf("HEAP_START=0x%08x, HEAP_END=0x%08x\n", BOARD_HEAP_START, BOARD_HEAP_END); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif +} diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.h new file mode 100644 index 0000000000..f971f871c1 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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/nuc980/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c new file mode 100644 index 0000000000..ddf8f00c3d --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c @@ -0,0 +1,764 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-4 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 --------------------------------------------------------------*/ + +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_AES_NAME "nu_AES" +#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_SHA_mutex; +static struct rt_mutex s_PRNG_mutex; + +static void nu_crypto_isr(int vector, void *param) +{ + /* Nothing */ +} + +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]; + + 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]); + + rt_mutex_take(&s_AES_mutex, RT_WAITING_FOREVER); + + AES_Open(CRPT, bEncrypt, u32OpMode, u32KeySize, AES_IN_OUT_SWAP); + AES_SetKey(CRPT, (uint32_t *)&au32SwapKey[0], u32KeySize); + AES_SetInitVect(CRPT, (uint32_t *)au32SwapIV); + + /* Setup AES DMA Description */ + AES_SetDMATransfer(CRPT, (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(CRPT); + + /* Start AES encryption/decryption */ + AES_Start(CRPT, 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_AESEIF_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(CRPT); + + rt_mutex_release(&s_AES_mutex); + + return RT_EOK; +} + +//Using PRNG instead of TRNG +static void nu_prng_open(uint32_t u32Seed) +{ + rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + + //Open PRNG 64 bits. But always return 32 bits + PRNG_Open(CRPT, PRNG_KEY_SIZE_64, PRNG_SEED_RELOAD, u32Seed); + + rt_mutex_release(&s_PRNG_mutex); +} + +static rt_uint32_t nu_prng_run(void) +{ + uint32_t au32RNGValue[2]; + + rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + + PRNG_Start(CRPT); + while ((CRPT->PRNG_CTL & CRPT_PRNG_CTL_BUSY_Msk)) {}; + + /* Clear PRNG interrupt status */ + PRNG_CLR_INT_FLAG(CRPT); + + PRNG_Read(CRPT, &au32RNGValue[0]); + + rt_mutex_release(&s_PRNG_mutex); + + 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 or out of SRAM + if (((rt_uint32_t)in % 4) != 0) + { + in = rt_malloc(symmetric_info->length); + 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 % 4) != 0) + { + out = rt_malloc(symmetric_info->length); + if (out == RT_NULL) + { + if (in_align_flag) + rt_free(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(out); + } + + if (in_align_flag) + { + rt_free(in); + } + + return RT_EOK; +} + +static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t u32Mode) +{ + SHA_Open(CRPT, u32OpMode, SHA_IN_OUT_SWAP, 0); + + //Setup SHA DMA + SHA_SetDMATransfer(CRPT, 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(CRPT); + SHA_Start(CRPT, u32Mode); + + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTSTS_HMACIF_Msk)) {}; + + if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_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(CRPT); +} + +static rt_err_t nu_sha_hash_run( + S_SHA_CONTEXT *psSHACtx, + uint32_t u32OpMode, + uint8_t *pu8InData, + uint32_t u32DataLen +) +{ + RT_ASSERT(psSHACtx != RT_NULL); + RT_ASSERT(pu8InData != RT_NULL); + + rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER); + + 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(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 & 3) //address not aligned 4 + { + psSHACtx->pu8SHATempBuf = rt_malloc(psSHACtx->u32BlockSize); + + if (psSHACtx->pu8SHATempBuf == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); + rt_mutex_release(&s_SHA_mutex); + 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(psSHACtx->u32BlockSize); + + if (psSHACtx->pu8SHATempBuf == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); + rt_mutex_release(&s_SHA_mutex); + return -RT_ENOMEM; + } + + psSHACtx->u32SHATempBufLen = 0; + } + + rt_memcpy(psSHACtx->pu8SHATempBuf, pu8SrcAddr, u32DataLen); + psSHACtx->u32SHATempBufLen += u32DataLen; + } + + rt_mutex_release(&s_SHA_mutex); + + 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 or out of SRAM + if (((rt_uint32_t)nu_in % 4) != 0) + { + nu_in = rt_malloc(length); + 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(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 % 4) != 0) + { + nu_out = rt_malloc(length); + 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(psSHACtx->pu8SHATempBuf); + psSHACtx->pu8SHATempBuf = RT_NULL; + psSHACtx->u32SHATempBufLen = 0; + } + else + { + SHABlockUpdate(u32SHAOpMode, (uint32_t)NULL, 0, CRYPTO_DMA_LAST); + } + + SHA_Read(CRPT, (uint32_t *)nu_out); + + if (out_align_flag) + { + rt_memcpy(out, nu_out, length); + rt_free(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_hash_ops nu_sha_ops = +{ + .update = nu_sha_update, + .finish = nu_sha_finish, +}; + +/* PRNG operation ------------------------------------------------------------*/ +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_SHA1: + 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); +#else + nu_prng_open(rt_tick_get()); +#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(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_FIFO); + 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); + 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); + RT_ASSERT(result == RT_EOK); +#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_CRYPTO, 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/nuc980/rtt_port/drv_ebi.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_ebi.c new file mode 100644 index 0000000000..61cb93044e --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_ebi.c @@ -0,0 +1,44 @@ +/**************************************************************************//** +* +* @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 +#include + +#if defined(BSP_USING_EBI) + +/* 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); + + if (!nu_ebi_bank_mask) + { + nu_sys_ipclk_enable(EBICKEN); + nu_sys_ip_reset(EBIRST); + } + + /* 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/nuc980/rtt_port/drv_ebi.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_ebi.h new file mode 100644 index 0000000000..c42a85e226 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_ebi.h @@ -0,0 +1,53 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-3-5 Philo First version +* +******************************************************************************/ +#ifndef __DRV_EBI_H___ +#define __DRV_EBI_H___ + +#include +#include + +#define MAX_BANK EBI_BANK2 + +/** + * @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 + * @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. + */ +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/nuc980/rtt_port/drv_emac.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c new file mode 100644 index 0000000000..cdba6f7a06 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c @@ -0,0 +1,637 @@ +/**************************************************************************//** +* +* @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 +#include +#include +#include +#include "lwipopts.h" + +#include "drv_sys.h" +#include "drv_pdma.h" + +/* Private define ---------------------------------------------------------------*/ +// RT_DEV_NAME_PREFIX e + +#if !defined(NU_EMAC_PDMA_MEMCOPY_THRESHOLD) + #define NU_EMAC_PDMA_MEMCOPY_THRESHOLD 1024 +#endif + +#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) +{ +#if defined(NU_EMAC_PDMA_MEMCOPY) + if ((count >= NU_EMAC_PDMA_MEMCOPY_THRESHOLD)) + return nu_pdma_memcpy(dest, src, count); +#endif + 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; + rt_err_t result = RT_EOK; + + 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); + + result = rt_sem_release(&psNuEmac->eth_sem); + RT_ASSERT(result == RT_EOK); + } + 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); + + rt_sem_init(&psNuEmac->eth_sem, "eth_sem", 0, RT_IPC_FLAG_FIFO); + + 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; + + if (psNuEmac->eth.link_status == RT_FALSE) + { + rt_kprintf("[%s]Stand here.\n", psNuEmac->name); + while (rt_sem_take(&psNuEmac->eth_sem, RT_WAITING_FOREVER) != RT_EOK); + rt_kprintf("[%s]Leave.\n", psNuEmac->name); + } + + buf = (rt_uint8_t *)EMAC_ClaimFreeTXBuf(&psNuEmac->memmgr); + + /* Get free TX buffer */ + if (buf == RT_NULL) + { + rt_sem_control(&psNuEmac->eth_sem, RT_IPC_CMD_RESET, 0); + + EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_TXCPIF_Msk); + EMAC_ENABLE_INT(EMAC, EMAC_INTEN_TXCPIEN_Msk); + + do + { + rt_sem_take(&psNuEmac->eth_sem, 1); + 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 & New trigger */ + EMAC_RecvPktDone(&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); + } + } + + 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]; + + 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); + } + + /* MDC CLK divider */ + outpw(REG_CLK_DIVCTL8, (inpw(REG_CLK_DIVCTL8) & ~0xFF) | 0xA0); + + 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/nuc980/rtt_port/drv_etimer.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_etimer.c new file mode 100644 index 0000000000..c009af16c7 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_etimer.c @@ -0,0 +1,297 @@ +/**************************************************************************//** +* +* @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 +#include + +/* Private define ---------------------------------------------------------------*/ +#define NU_TIMER_DEVICE(etimer) (nu_etimer_t)(etimer) + +enum +{ + ETIMER_START = -1, +#if defined(BSP_USING_TIMER0) + ETIMER0_IDX, +#endif +#if defined(BSP_USING_TIMER1) + ETIMER1_IDX, +#endif +#if defined(BSP_USING_TIMER2) + ETIMER2_IDX, +#endif +#if defined(BSP_USING_TIMER3) + ETIMER3_IDX, +#endif +#if defined(BSP_USING_TIMER4) + ETIMER4_IDX, +#endif + /* BSP_USING_TIMER5 is reserved for Systick usage. */ + 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_TIMER0) + { + .name = "etimer0", + .idx = 0, + .irqn = IRQ_TIMER0, + .rstidx = TIMER0RST, + .clkidx = TIMER0CKEN, + }, +#endif +#if defined(BSP_USING_TIMER1) + { + .name = "etimer1", + .idx = 1, + .irqn = IRQ_TIMER1, + .rstidx = TIMER1RST, + .clkidx = TIMER1CKEN, + }, +#endif +#if defined(BSP_USING_TIMER2) + { + .name = "etimer2", + .idx = 2, + .irqn = IRQ_TIMER2, + .rstidx = TIMER2RST, + .clkidx = TIMER2CKEN, + }, +#endif +#if defined(BSP_USING_TIMER3) + { + .name = "etimer3", + .idx = 3, + .irqn = IRQ_TIMER3, + .rstidx = TIMER3RST, + .clkidx = TIMER3CKEN, + }, +#endif +#if defined(BSP_USING_TIMER4) + { + .name = "etimer4", + .idx = 4, + .irqn = IRQ_TIMER4, + .rstidx = TIMER4RST, + .clkidx = TIMER4CKEN, + }, +#endif + /* BSP_USING_TIMER5 is reserved for Systick usage. */ +}; + +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_TIMER) && defined(RT_USING_HWTIMER) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.c new file mode 100644 index 0000000000..71d8b6f012 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.c @@ -0,0 +1,344 @@ +/**************************************************************************//** +* +* @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 +#include +#include +#include +#include + +/* Private define ---------------------------------------------------------------*/ + +#define PORT_OFFSET 0x40 +#define IRQ_MAX_NUM 16 //Max support 32 + +/* 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 IRQn_Type au32GPIRQ[NU_PORT_CNT] = {IRQ_GPA, IRQ_GPB, IRQ_GPC, IRQ_GPD, IRQ_GPE, IRQ_GPF, IRQ_GPG}; + +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); + + 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] <= 'H') + return ((name[1] - 'A') * 0x10) + number; + + if (name[1] >= 'a' && name[1] <= 'h') + 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_T *PORT; + + if (nu_port_check(pin)) + return; + + PORT = (GPIO_T *)(PA_BA + (NU_GET_PORT(pin) * PORT_OFFSET)); + + if (mode == PIN_MODE_INPUT_PULLUP) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT); + GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_PULL_UP); + } + else if (mode == PIN_MODE_INPUT_PULLDOWN) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT); + GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_PULL_DOWN); + } + else 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); + GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_DISABLE); + } + else if (mode == PIN_MODE_OUTPUT_OD) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_OPEN_DRAIN); + GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_DISABLE); + } +} + +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 void nu_gpio_isr(int vector, void *param) +{ + rt_uint32_t int_status; + GPIO_T *PORT = (GPIO_T *)param; + rt_uint32_t port_idx = ((rt_uint32_t)PORT - PA_BA) / PORT_OFFSET ; + + int_status = PORT->INTSRC; + pin_irq_hdr(int_status, port_idx); + PORT->INTSRC = int_status; +} + +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; + IRQn_Type irqn; + + 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_BA + (NU_GET_PORT(pin) * PORT_OFFSET)); + + irqn = au32GPIRQ[NU_GET_PORT(pin)]; + + 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); + + rt_hw_interrupt_umask(irqn); + + } + else + { + GPIO_DisableInt(PORT, NU_GET_PINS(pin)); + rt_hw_interrupt_mask(irqn); + } + +exit_nu_gpio_irq_enable: + + rt_hw_interrupt_enable(level); + return -(ret); +} + +int rt_hw_gpio_init(void) +{ + char szTmp[16]; + int i; + 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; + } + + for (i = 0; i < NU_PORT_CNT ; i++) + { + IRQn_Type irqn = au32GPIRQ[i]; + snprintf(szTmp, sizeof(szTmp), "gpio-%d", i); + rt_hw_interrupt_install(irqn, nu_gpio_isr, (void *)(PA_BA + (i * PORT_OFFSET)), szTmp); + rt_hw_interrupt_set_type(irqn, HIGH_LEVEL_SENSITIVE); + } + + nu_sys_ipclk_enable(GPIOCKEN); + + 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/nuc980/rtt_port/drv_gpio.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.h new file mode 100644 index 0000000000..ad8792f796 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_gpio.h @@ -0,0 +1,33 @@ +/**************************************************************************//** +* +* @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_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/nuc980/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c new file mode 100644 index 0000000000..b260b7fc18 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c @@ -0,0 +1,394 @@ +/**************************************************************************//** +* +* @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 + +#if defined( BSP_USING_I2C) + +#include +#include +#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 + +enum +{ + I2C_START = -1, +#if defined(BSP_USING_I2C0) + I2C0_IDX, +#endif +#if defined(BSP_USING_I2C1) + I2C1_IDX, +#endif +#if defined(BSP_USING_I2C2) + I2C2_IDX, +#endif +#if defined(BSP_USING_I2C3) + I2C3_IDX, +#endif + I2C_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +typedef struct _nu_i2c_bus +{ + struct rt_i2c_bus_device parent; + I2C_T *I2C; + struct rt_i2c_msg *msg; + char *device_name; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +} nu_i2c_bus_t; + +/* Private variables ------------------------------------------------------------*/ + + +static nu_i2c_bus_t nu_i2c_arr [ ] = +{ +#if defined(BSP_USING_I2C0) + { + .I2C = I2C0, + .device_name = "i2c0", + .rstidx = I2C0RST, + .clkidx = I2C0CKEN, + }, +#endif +#if defined(BSP_USING_I2C1) + { + .I2C = I2C1, + .device_name = "i2c1", + .rstidx = I2C1RST, + .clkidx = I2C1CKEN, + }, +#endif +#if defined(BSP_USING_I2C2) + { + .I2C = I2C2, + .device_name = "i2c2", + .rstidx = I2C2RST, + .clkidx = I2C2CKEN, + }, +#endif +#if defined(BSP_USING_I2C3) + { + .I2C = I2C3, + .device_name = "i2c3", + .rstidx = I2C3RST, + .clkidx = I2C3CKEN, + }, +#endif +}; + +/* Private functions ------------------------------------------------------------*/ +#if defined(BSP_USING_I2C) +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, addr2; + rt_err_t ret; + + + if (flags & RT_I2C_ADDR_10BIT) + { + nu_i2c->I2C->CTL1 |= I2C_CTL1_ADDR10EN_Msk; + addr1 = 0xf0 | ((msg->addr >> 7) & 0x06); + addr2 = msg->addr & 0xff; + + LOG_D("address1: %d, address2: %d\n", addr1, addr2); + + ret = nu_i2c_send_data(nu_i2c, addr1); + if (ret != RT_EOK) /* for timeout condition */ + return -RT_EIO; + + if ((I2C_GET_STATUS(nu_i2c->I2C) != NU_I2C_MASTER_STATUS_TRANSMIT_ADDRESS_ACK) && !ignore_nack) + { + LOG_E("NACK: sending first address failed\n"); + + return -RT_EIO; + } + + ret = nu_i2c_send_data(nu_i2c, addr2); + if (ret != RT_EOK) /* for timeout condition */ + return -RT_EIO; + + if ((I2C_GET_STATUS(nu_i2c->I2C) != NU_I2C_MASTER_STATUS_TRANSMIT_ADDRESS_ACK) && !ignore_nack) + { + LOG_E("NACK: sending second address failed\n"); + + return -RT_EIO; + } + + if (flags & RT_I2C_RD) + { + LOG_D("send repeated START signal\n"); + + 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 */ + return -RT_EIO; + + if ((I2C_GET_STATUS(nu_i2c->I2C) != NU_I2C_MASTER_STATUS_REPEAT_START) && !ignore_nack) + { + LOG_E("sending repeated START failed\n"); + + return -RT_EIO; + } + + addr1 |= 0x01; + + ret = nu_i2c_send_data(nu_i2c, addr1); + if (ret != RT_EOK) /* for timeout condition */ + return -RT_EIO; + + if ((I2C_GET_STATUS(nu_i2c->I2C) != NU_I2C_MASTER_STATUS_RECEIVE_ADDRESS_ACK) && !ignore_nack) + { + LOG_E("NACK: sending read address failed\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) ? NU_I2C_MASTER_STATUS_RECEIVE_ADDRESS_ACK : NU_I2C_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) != NU_I2C_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) != NU_I2C_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) != NU_I2C_MASTER_STATUS_RECEIVE_DATA_ACK) + { + i = 0; + break; + } + } + else + { + if (I2C_GET_STATUS(nu_i2c->I2C) != NU_I2C_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) != NU_I2C_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) == NU_I2C_MASTER_STATUS_BUS_RELEASED); + if (I2C_GET_STATUS(nu_i2c->I2C) != NU_I2C_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) +{ + int i; + rt_err_t ret = RT_EOK; + + for (i = (I2C_START + 1); i < I2C_CNT; i++) + { + + nu_sys_ipclk_enable(nu_i2c_arr[i].clkidx); + nu_sys_ip_reset(nu_i2c_arr[i].rstidx); + + nu_i2c_configure(&nu_i2c_arr[i]); + ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].device_name); + RT_ASSERT(RT_EOK == ret); + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_i2c_init); + +#endif /* BSP_USING_I2C */ + diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.h new file mode 100644 index 0000000000..6a314fa0b9 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.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-11-11 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_I2C_H__ +#define __DRV_I2C_H__ + +#define NU_I2C_MASTER_STATUS_START 0x08UL +#define NU_I2C_MASTER_STATUS_REPEAT_START 0x10UL +#define NU_I2C_MASTER_STATUS_TRANSMIT_ADDRESS_ACK 0x18UL +#define NU_I2C_MASTER_STATUS_TRANSMIT_ADDRESS_NACK 0x20UL +#define NU_I2C_MASTER_STATUS_TRANSMIT_DATA_ACK 0x28UL +#define NU_I2C_MASTER_STATUS_TRANSMIT_DATA_NACK 0x30UL +#define NU_I2C_MASTER_STATUS_ARBITRATION_LOST 0x38UL +#define NU_I2C_MASTER_STATUS_RECEIVE_ADDRESS_ACK 0x40UL +#define NU_I2C_MASTER_STATUS_RECEIVE_ADDRESS_NACK 0x48UL +#define NU_I2C_MASTER_STATUS_RECEIVE_DATA_ACK 0x50UL +#define NU_I2C_MASTER_STATUS_RECEIVE_DATA_NACK 0x58UL +#define NU_I2C_MASTER_STATUS_BUS_ERROR 0x00UL +#define NU_I2C_MASTER_STATUS_BUS_RELEASED 0xF8UL + +#define NU_I2C_SLAVE_STATUS_TRANSMIT_REPEAT_START_OR_STOP 0xA0UL +#define NU_I2C_SLAVE_STATUS_TRANSMIT_ADDRESS_ACK 0xA8UL +#define NU_I2C_SLAVE_STATUS_TRANSMIT_DATA_NACK 0xC0UL +#define NU_I2C_SLAVE_STATUS_RECEIVE_ADDRESS_ACK 0x60UL +#define NU_I2C_SLAVE_STATUS_RECEIVE_DATA_ACK 0x80UL + +#endif /* __DRV_I2C_H__ */ diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.c new file mode 100644 index 0000000000..c8d410281d --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.c @@ -0,0 +1,590 @@ +/**************************************************************************//** +* +* @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 + +/* Private define ---------------------------------------------------------------*/ +#define DBG_ENABLE +#define DBG_LEVEL DBG_LOG +#define DBG_SECTION_NAME "i2s" +#define DBG_COLOR +#include + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_i2s_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps); +static rt_err_t nu_i2s_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps); +static rt_err_t nu_i2s_init(struct rt_audio_device *audio); +static rt_err_t nu_i2s_start(struct rt_audio_device *audio, int stream); +static rt_err_t nu_i2s_stop(struct rt_audio_device *audio, int stream); +static void nu_i2s_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info); +/* Public functions -------------------------------------------------------------*/ +rt_err_t nu_i2s_acodec_register(nu_acodec_ops_t); + +/* Private variables ------------------------------------------------------------*/ +static struct nu_i2s g_nu_i2s_dev = +{ + .name = "sound0", + .i2s_base = I2S0, + .i2s_rst = I2S0_RST, + .i2s_dais = { + [NU_I2S_DAI_PLAYBACK] = { + .pdma_perp = PDMA_I2S0_TX, + }, + [NU_I2S_DAI_CAPTURE] = { + .pdma_perp = PDMA_I2S0_RX, + } + } +}; + +static void nu_pdma_i2s_rx_cb(void *pvUserData, uint32_t u32EventFilter) +{ + nu_i2s_t psNuI2s = (nu_i2s_t)pvUserData; + nu_i2s_dai_t psNuI2sDai; + + RT_ASSERT(psNuI2s != RT_NULL); + psNuI2sDai = &psNuI2s->i2s_dais[NU_I2S_DAI_CAPTURE]; + + if (u32EventFilter & NU_PDMA_EVENT_TRANSFER_DONE) + { + // Report a buffer ready. + rt_uint8_t *pbuf_old = &psNuI2sDai->fifo[psNuI2sDai->fifo_block_idx * NU_I2S_DMA_BUF_BLOCK_SIZE] ; + psNuI2sDai->fifo_block_idx = (psNuI2sDai->fifo_block_idx + 1) % NU_I2S_DMA_BUF_BLOCK_NUMBER; + + /* Report upper layer. */ + rt_audio_rx_done(&psNuI2s->audio, pbuf_old, NU_I2S_DMA_BUF_BLOCK_SIZE); + } +} + +static void nu_pdma_i2s_tx_cb(void *pvUserData, uint32_t u32EventFilter) +{ + nu_i2s_t psNuI2s = (nu_i2s_t)pvUserData; + nu_i2s_dai_t psNuI2sDai; + + RT_ASSERT(psNuI2s != RT_NULL); + psNuI2sDai = &psNuI2s->i2s_dais[NU_I2S_DAI_PLAYBACK]; + + if (u32EventFilter & NU_PDMA_EVENT_TRANSFER_DONE) + { + rt_audio_tx_complete(&psNuI2s->audio); + psNuI2sDai->fifo_block_idx = (psNuI2sDai->fifo_block_idx + 1) % NU_I2S_DMA_BUF_BLOCK_NUMBER; + } +} + +static rt_err_t nu_i2s_pdma_sc_config(nu_i2s_t psNuI2s, E_NU_I2S_DAI dai) +{ + rt_err_t result = RT_EOK; + I2S_T *i2s_base; + nu_i2s_dai_t psNuI2sDai; + int i; + uint32_t u32Src, u32Dst; + nu_pdma_cb_handler_t pfm_pdma_cb; + + RT_ASSERT(psNuI2s != RT_NULL); + + /* Get base address of i2s register */ + i2s_base = psNuI2s->i2s_base; + psNuI2sDai = &psNuI2s->i2s_dais[dai]; + + switch ((int)dai) + { + case NU_I2S_DAI_PLAYBACK: + pfm_pdma_cb = nu_pdma_i2s_tx_cb; + u32Src = (uint32_t)&psNuI2sDai->fifo[0]; + u32Dst = (uint32_t)&i2s_base->TXFIFO; + break; + + case NU_I2S_DAI_CAPTURE: + pfm_pdma_cb = nu_pdma_i2s_rx_cb; + u32Src = (uint32_t)&i2s_base->RXFIFO; + u32Dst = (uint32_t)&psNuI2sDai->fifo[0]; + break; + + default: + return -RT_EINVAL; + } + + result = nu_pdma_callback_register(psNuI2sDai->pdma_chanid, + pfm_pdma_cb, + (void *)psNuI2s, + 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(psNuI2sDai->pdma_chanid, // Channel ID + psNuI2sDai->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 + psNuI2sDai->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(psNuI2sDai->pdma_chanid, psNuI2sDai->pdma_descs[0], 0); + RT_ASSERT(result == RT_EOK); + + return result; +} + +static rt_bool_t nu_i2s_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_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; + rt_uint32_t real_samplerate; + + /* 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; + + real_samplerate = I2S_Open(psNuI2s->i2s_base, + (psNuI2s->AcodecOps->role == NU_ACODEC_ROLE_MASTER) ? I2S_MODE_SLAVE : I2S_MODE_MASTER, + pconfig->samplerate, + (((pconfig->samplebits / 8) - 1) << I2S_CTL0_DATWIDTH_Pos), + (pconfig->channels == 1) ? I2S_ENABLE_MONO : I2S_DISABLE_MONO, + I2S_FORMAT_I2S); + LOG_I("Open I2S."); + + /* Open I2S0 interface and set to slave mode, stereo channel, I2S format */ + if (pconfig->samplerate != real_samplerate) + { + LOG_W("Real sample rate: %d Hz != preferred sample rate: %d Hz\n", real_samplerate, pconfig->samplerate); + } + + /* Set MCLK and enable MCLK */ + I2S_EnableMCLK(psNuI2s->i2s_base, __HXT); + + /* 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; + + /* Reset this module */ + SYS_ResetModule(psNuI2s->i2s_rst); + + 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: + { + nu_i2s_pdma_sc_config(psNuI2s, NU_I2S_DAI_PLAYBACK); + + /* Start TX DMA */ + I2S_ENABLE_TXDMA(psNuI2s->i2s_base); + + /* Enable I2S Tx function */ + I2S_ENABLE_TX(psNuI2s->i2s_base); + + LOG_I("Start replay."); + } + break; + + case AUDIO_STREAM_RECORD: + { + nu_i2s_pdma_sc_config(psNuI2s, NU_I2S_DAI_CAPTURE); + + /* Start RX DMA */ + I2S_ENABLE_RXDMA(psNuI2s->i2s_base); + + /* Enable I2S Rx function */ + I2S_ENABLE_RX(psNuI2s->i2s_base); + + 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]; + + // Disable TX + I2S_DISABLE_TXDMA(psNuI2s->i2s_base); + I2S_DISABLE_TX(psNuI2s->i2s_base); + + LOG_I("Stop replay."); + break; + + case AUDIO_STREAM_RECORD: + psNuI2sDai = &psNuI2s->i2s_dais[NU_I2S_DAI_CAPTURE]; + + // Disable RX + I2S_DISABLE_RXDMA(psNuI2s->i2s_base); + I2S_DISABLE_RX(psNuI2s->i2s_base); + + LOG_I("Stop record."); + break; + + default: + return -RT_EINVAL; + } + + /* Stop DMA transfer. */ + nu_pdma_channel_terminate(psNuI2sDai->pdma_chanid); + + /* Close I2S */ + if (!(psNuI2s->i2s_base->CTL0 & (I2S_CTL0_TXEN_Msk | I2S_CTL0_RXEN_Msk))) + { + I2S_DisableMCLK(psNuI2s->i2s_base); + I2S_Close(psNuI2s->i2s_base); + LOG_I("Close I2S."); + } + + /* Silence */ + rt_memset((void *)psNuI2sDai->fifo, 0, NU_I2S_DMA_FIFO_SIZE); + psNuI2sDai->fifo_block_idx = 0; + + 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; + + info->buffer = (rt_uint8_t *)psNuI2s->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_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 +}; + +static rt_err_t nu_hw_i2s_pdma_allocate(nu_i2s_dai_t psNuI2sDai) +{ + /* Allocate I2S nu_dma channel */ + if ((psNuI2sDai->pdma_chanid = nu_pdma_channel_allocate(psNuI2sDai->pdma_perp)) < 0) + { + goto nu_hw_i2s_pdma_allocate; + } + + return RT_EOK; + +nu_hw_i2s_pdma_allocate: + + return -(RT_ERROR); +} + +int rt_hw_i2s_init(void) +{ + int i = 0; + nu_i2s_dai_t psNuI2sDai; + + for (i = 0; i < NU_I2S_DAI_CNT; i++) + { + uint8_t *pu8ptr = rt_malloc(NU_I2S_DMA_FIFO_SIZE); + psNuI2sDai = &g_nu_i2s_dev.i2s_dais[i]; + psNuI2sDai->fifo = pu8ptr; + rt_memset(pu8ptr, 0, NU_I2S_DMA_FIFO_SIZE); + RT_ASSERT(psNuI2sDai->fifo != RT_NULL); + + psNuI2sDai->pdma_chanid = -1; + psNuI2sDai->fifo_block_idx = 0; + RT_ASSERT(nu_hw_i2s_pdma_allocate(psNuI2sDai) == RT_EOK); + + RT_ASSERT(nu_pdma_sgtbls_allocate(&psNuI2sDai->pdma_descs[0], NU_I2S_DMA_BUF_BLOCK_NUMBER) == RT_EOK); + } + + /* 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); + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_i2s_init); +#endif //#if defined(BSP_USING_I2S) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2s.h new file mode 100644 index 0000000000..3fe99f3e3b --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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 +#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; + I2S_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/nuc980/rtt_port/drv_pdma.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c new file mode 100644 index 0000000000..dc83fe5efe --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c @@ -0,0 +1,1131 @@ +/**************************************************************************//** +* +* @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 + +#if defined(BSP_USING_PDMA) + +#include +#include +#include +#include +#include "drv_sys.h" + +/* 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 (2*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) +#define NU_PDMA_CH_HALF_Msk (((1 << PDMA_CH_MAX) - 1) << NU_PDMA_CH_Pos) +#define NU_PDMA_GET_BASE(ch) (PDMA_T *)((((ch)/PDMA_CH_MAX)>0)?PDMA1_BA:PDMA0_BA) +#define NU_PDMA_GET_MOD_CHIDX(ch) ((ch)%PDMA_CH_MAX) + +/* 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 +{ + struct nu_pdma_chn_cb m_sCB_Event; + struct nu_pdma_chn_cb m_sCB_Trigger; + struct nu_pdma_chn_cb m_sCB_Disable; + + nu_pdma_desc_t *m_ppsSgtbl; + uint32_t m_u32WantedSGTblNum; + + 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 u32TransferCnt, 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 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 void nu_pdma_isr(int vector, void *pvdata); + +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_UART8_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART9_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_QSPI0_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_SPI0_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_SPI1_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_I2C0_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_I2C1_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_I2C2_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_I2C3_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_UART8_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART9_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_QSPI0_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_SPI0_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_SPI1_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_I2C0_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_I2C1_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_I2C2_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_I2C3_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]; + +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) +{ + if (nu_pdma_inited) + return; + + nu_pdma_chn_mask = ~(NU_PDMA_CH_Msk); + rt_memset(nu_pdma_chn_arr, 0x00, sizeof(nu_pdma_chn_t)); + + nu_sys_ipclk_enable(PDMA0CKEN); + nu_sys_ipclk_enable(PDMA1CKEN); + + nu_sys_ip_reset(PDMA0RST); + nu_sys_ip_reset(PDMA1RST); + + /* Initialize PDMA0 setting */ + PDMA_Open(PDMA0, NU_PDMA_CH_HALF_Msk); + PDMA_Close(PDMA0); + + /* Register PDMA0 ISR */ + rt_hw_interrupt_install(IRQ_PDMA0, nu_pdma_isr, (void *)PDMA0, "pdma0"); + rt_hw_interrupt_umask(IRQ_PDMA0); + + /* Initialize PDMA1 setting */ + PDMA_Open(PDMA1, NU_PDMA_CH_HALF_Msk); + PDMA_Close(PDMA1); + + /* Register PDMA1 ISR */ + rt_hw_interrupt_install(IRQ_PDMA1, nu_pdma_isr, (void *)PDMA1, "pdma1"); + rt_hw_interrupt_umask(IRQ_PDMA1); + + /* Assign first SG table address to SRAM's start address */ + PDMA0->SCATBA = PDMA1->SCATBA = BOARD_SDRAM_START; + + nu_pdma_inited = 1; +} + +static void nu_pdma_channel_enable(int i32ChannID) +{ + PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID); + PDMA_Open(PDMA, 1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID)); +} + +static inline void nu_pdma_channel_disable(int i32ChannID) +{ + PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID); + PDMA->CHCTL &= ~(1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID)); +} + +static inline void nu_pdma_channel_reset(int i32ChannID) +{ + PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID); + PDMA->CHRST = (1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID)); +} + +void nu_pdma_channel_terminate(int i32ChannID) +{ + PDMA_T *PDMA; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_pdma_channel_terminate; + + PDMA = NU_PDMA_GET_BASE(i32ChannID); + + // Reset specified channel ID + nu_pdma_channel_reset(i32ChannID); + + // Clean descriptor table control register. + PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)].CTL = 0UL; + + PDMA->CHCTL |= (1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID)); + +exit_pdma_channel_terminate: + + return; +} + +static rt_err_t nu_pdma_timeout_set(int i32ChannID, int i32Timeout_us) +{ + rt_err_t ret = RT_EINVAL; + PDMA_T *PDMA = NULL; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_timeout_set; + + PDMA = NU_PDMA_GET_BASE(i32ChannID); + + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32IdleTimeout_us = i32Timeout_us; + + if (i32Timeout_us && (NU_PDMA_GET_MOD_CHIDX(i32ChannID) < PDMA_CH_MAX)) // Limit + { + uint32_t u32HCLK = sysGetClock(SYS_HCLK) * 1000000; + + uint32_t u32ToClk_Max = u32HCLK / (1 << 8); + uint32_t u32Divider = ((i32Timeout_us * u32ToClk_Max) / 1000000) / (1 << 16); + uint32_t u32TOutCnt = ((i32Timeout_us * u32ToClk_Max) / 1000000) % (1 << 16); + + PDMA_DisableTimeout(PDMA, 1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID)); + PDMA_EnableInt(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID), PDMA_INT_TIMEOUT); // Interrupt type + + if (u32Divider > 7) + { + u32Divider = 7; + u32TOutCnt = (1 << 16); + } + PDMA->TOUTPSC |= (u32Divider << (PDMA_TOUTPSC_TOUTPSC1_Pos * NU_PDMA_GET_MOD_CHIDX(i32ChannID))); + PDMA_SetTimeOut(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID), 1, u32TOutCnt); + + ret = RT_EOK; + } + else + { + PDMA_DisableInt(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID), PDMA_INT_TIMEOUT); // Interrupt type + PDMA_DisableTimeout(PDMA, 1 << NU_PDMA_GET_MOD_CHIDX(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_filtering_set(int i32ChannID, uint32_t u32EventFilter) +{ + rt_err_t ret = RT_EINVAL; + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_filtering_set; + + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter = u32EventFilter; + + ret = RT_EOK; + +exit_nu_pdma_filtering_set: + + return -(ret) ; +} + +uint32_t nu_pdma_filtering_get(int i32ChannID) +{ + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_filtering_get; + + return nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter; + +exit_nu_pdma_filtering_get: + + return 0; +} + +rt_err_t nu_pdma_callback_register(int i32ChannID, nu_pdma_chn_cb_t psChnCb) +{ + rt_err_t ret = RT_EINVAL; + nu_pdma_chn_cb_t psChnCb_Current = RT_NULL; + + RT_ASSERT(psChnCb != RT_NULL); + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_callback_register; + + switch (psChnCb->m_eCBType) + { + case eCBType_Event: + psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Event; + break; + case eCBType_Trigger: + psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Trigger; + break; + case eCBType_Disable: + psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Disable; + break; + default: + goto exit_nu_pdma_callback_register; + } + + psChnCb_Current->m_pfnCBHandler = psChnCb->m_pfnCBHandler; + psChnCb_Current->m_pvUserData = psChnCb->m_pvUserData; + + ret = RT_EOK; + +exit_nu_pdma_callback_register: + + return -(ret) ; +} + +nu_pdma_cb_handler_t nu_pdma_callback_hijack(int i32ChannID, nu_pdma_cbtype_t eCBType, nu_pdma_chn_cb_t psChnCb_Hijack) +{ + nu_pdma_chn_cb_t psChnCb_Current = RT_NULL; + struct nu_pdma_chn_cb sChnCB_Tmp; + + RT_ASSERT(psChnCb_Hijack != NULL); + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_callback_hijack; + + switch (eCBType) + { + case eCBType_Event: + psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Event; + break; + case eCBType_Trigger: + psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Trigger; + break; + case eCBType_Disable: + psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Disable; + break; + default: + goto exit_nu_pdma_callback_hijack; + } + + /* Backup */ + sChnCB_Tmp.m_pfnCBHandler = psChnCb_Current->m_pfnCBHandler; + sChnCB_Tmp.m_pvUserData = psChnCb_Current->m_pvUserData; + + /* Update */ + psChnCb_Current->m_pfnCBHandler = psChnCb_Hijack->m_pfnCBHandler; + psChnCb_Current->m_pvUserData = psChnCb_Hijack->m_pvUserData; + + /* Restore */ + psChnCb_Hijack->m_pfnCBHandler = sChnCB_Tmp.m_pfnCBHandler; + psChnCb_Hijack->m_pvUserData = sChnCB_Tmp.m_pvUserData; + +exit_nu_pdma_callback_hijack: + + return sChnCB_Tmp.m_pfnCBHandler; +} + +static int nu_pdma_non_transfer_count_get(int32_t i32ChannID) +{ + PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID); + return ((PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(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; + PDMA_T *PDMA; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_transferred_byte_get; + + PDMA = NU_PDMA_GET_BASE(i32ChannID); + + i32BitWidth = PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(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, uint32_t u32BeSilent) +{ + nu_pdma_periph_ctl_t *psPeriphCtl = NULL; + PDMA_T *PDMA = 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; + + PDMA = NU_PDMA_GET_BASE(i32ChannID); + + 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); + + } + + /* Be silent */ + if (u32BeSilent) + dma_desc->CTL |= PDMA_DSCT_CTL_TBINTDIS_Msk; + + ret = RT_EOK; + +exit_nu_pdma_desc_setup: + + return -(ret); +} + +rt_err_t nu_pdma_sgtbls_allocate(nu_pdma_desc_t *ppsSgtbls, int num) +{ + int i; + nu_pdma_desc_t psSgTblHead; + + RT_ASSERT(ppsSgtbls != NULL); + RT_ASSERT(num > 0); + + psSgTblHead = (nu_pdma_desc_t) rt_malloc_align(sizeof(DSCT_T) * num, 32); + RT_ASSERT(psSgTblHead != RT_NULL); + + rt_memset((void *)psSgTblHead, 0, sizeof(DSCT_T) * num); + + for (i = 0; i < num; i++) + ppsSgtbls[i] = &psSgTblHead[i]; + + return RT_EOK; +} + +void nu_pdma_sgtbls_free(nu_pdma_desc_t *ppsSgtbls, int num) +{ + nu_pdma_desc_t psSgTblHead; + + RT_ASSERT(ppsSgtbls != NULL); + psSgTblHead = *ppsSgtbls; + RT_ASSERT(psSgTblHead != NULL); + + rt_free_align(psSgTblHead); +} + +static void _nu_pdma_transfer(int i32ChannID, uint32_t u32Peripheral, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us) +{ + PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID); + nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos]; + + PDMA_DisableTimeout(PDMA, 1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID)); + + PDMA_EnableInt(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID), PDMA_INT_TRANS_DONE); + + nu_pdma_timeout_set(i32ChannID, u32IdleTimeout_us); + + /* Set scatter-gather mode and head */ + PDMA_SetTransferMode(PDMA, + NU_PDMA_GET_MOD_CHIDX(i32ChannID), + u32Peripheral, + (head->NEXT != 0) ? 1 : 0, + (uint32_t)head); + +#if defined(BSP_USING_MMU) + /* Writeback data in dcache to memory before transferring. */ + { + static uint32_t bNonCacheAlignedWarning = 1; + nu_pdma_desc_t next = head; + while (next != RT_NULL) + { + uint32_t u32TxCnt = ((next->CTL & PDMA_DSCT_CTL_TXCNT_Msk) >> PDMA_DSCT_CTL_TXCNT_Pos) + 1; + uint32_t u32DataWidth = (1 << ((next->CTL & PDMA_DSCT_CTL_TXWIDTH_Msk) >> PDMA_DSCT_CTL_TXWIDTH_Pos)); + uint32_t u32SrcCtl = (next->CTL & PDMA_DSCT_CTL_SAINC_Msk); + uint32_t u32DstCtl = (next->CTL & PDMA_DSCT_CTL_DAINC_Msk); + uint32_t u32FlushLen = u32TxCnt * u32DataWidth; + + /* Flush Src buffer into memory. */ + if ((u32SrcCtl == PDMA_SAR_INC)) // for M2P, M2M + mmu_clean_invalidated_dcache(next->SA, u32FlushLen); + + /* Flush Dst buffer into memory. */ + if ((u32DstCtl == PDMA_DAR_INC)) // for P2M, M2M + mmu_clean_invalidated_dcache(next->DA, u32FlushLen); + + /* Flush descriptor into memory */ + if (!((rt_uint32_t)next & NONCACHEABLE)) + mmu_clean_invalidated_dcache((rt_uint32_t)next, sizeof(DSCT_T)); + + if (bNonCacheAlignedWarning) + { + if ((u32FlushLen & (CACHE_LINE_SIZE - 1)) || + (next->SA & (CACHE_LINE_SIZE - 1)) || + (next->DA & (CACHE_LINE_SIZE - 1)) || + ((rt_uint32_t)next & (CACHE_LINE_SIZE - 1))) + { + /* + Race-condition avoidance between DMA-transferring and DCache write-back: + Source, destination, DMA descriptor address and length should be aligned at len(CACHE_LINE_SIZE) + */ + bNonCacheAlignedWarning = 0; + rt_kprintf("[PDMA-W]\n"); + } + } + + next = (nu_pdma_desc_t)next->NEXT; + + if (next == head) break; + } + } +#endif + + /* If peripheral is M2M, trigger it. */ + if (u32Peripheral == PDMA_MEM) + { + PDMA_Trigger(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID)); + } + else if (psPdmaChann->m_sCB_Trigger.m_pfnCBHandler) + { + psPdmaChann->m_sCB_Trigger.m_pfnCBHandler(psPdmaChann->m_sCB_Trigger.m_pvUserData, psPdmaChann->m_sCB_Trigger.m_u32Reserved); + } +} + +static void _nu_pdma_free_sgtbls(nu_pdma_chn_t *psPdmaChann) +{ + if (psPdmaChann->m_ppsSgtbl) + { + nu_pdma_sgtbls_free(psPdmaChann->m_ppsSgtbl, psPdmaChann->m_u32WantedSGTblNum); + rt_free_align((void *)psPdmaChann->m_ppsSgtbl); + psPdmaChann->m_ppsSgtbl = RT_NULL; + psPdmaChann->m_u32WantedSGTblNum = 0; + } +} + +static rt_err_t _nu_pdma_transfer_chain(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, uint32_t u32TransferCnt, uint32_t u32IdleTimeout_us) +{ + int i = 0; + rt_err_t ret = RT_ERROR; + nu_pdma_periph_ctl_t *psPeriphCtl = NULL; + nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos]; + + nu_pdma_memctrl_t eMemCtl = nu_pdma_channel_memctrl_get(i32ChannID); + + rt_uint32_t u32Offset = 0; + rt_uint32_t u32TxCnt = 0; + + psPeriphCtl = &psPdmaChann->m_spPeripCtl; + + if (psPdmaChann->m_u32WantedSGTblNum != (u32TransferCnt / NU_PDMA_MAX_TXCNT + 1)) + { + if (psPdmaChann->m_u32WantedSGTblNum > 0) + _nu_pdma_free_sgtbls(psPdmaChann); + + psPdmaChann->m_u32WantedSGTblNum = u32TransferCnt / NU_PDMA_MAX_TXCNT + 1; + + psPdmaChann->m_ppsSgtbl = (nu_pdma_desc_t *)rt_malloc_align(sizeof(nu_pdma_desc_t) * psPdmaChann->m_u32WantedSGTblNum, 4); + if (!psPdmaChann->m_ppsSgtbl) + goto exit__nu_pdma_transfer_chain; + + ret = nu_pdma_sgtbls_allocate(psPdmaChann->m_ppsSgtbl, psPdmaChann->m_u32WantedSGTblNum); + if (ret != RT_EOK) + goto exit__nu_pdma_transfer_chain; + } + + for (i = 0; i < psPdmaChann->m_u32WantedSGTblNum; i++) + { + u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt; + + ret = nu_pdma_desc_setup(i32ChannID, + psPdmaChann->m_ppsSgtbl[i], + u32DataWidth, + (eMemCtl & 0x2ul) ? u32AddrSrc + u32Offset : u32AddrSrc, /* Src address is Inc or not. */ + (eMemCtl & 0x1ul) ? u32AddrDst + u32Offset : u32AddrDst, /* Dst address is Inc or not. */ + u32TxCnt, + ((i + 1) == psPdmaChann->m_u32WantedSGTblNum) ? RT_NULL : psPdmaChann->m_ppsSgtbl[i + 1], + ((i + 1) == psPdmaChann->m_u32WantedSGTblNum) ? 0 : 1); // Silent, w/o TD interrupt + + if (ret != RT_EOK) + goto exit__nu_pdma_transfer_chain; + + u32TransferCnt -= u32TxCnt; + u32Offset += (u32TxCnt * u32DataWidth / 8); + } + + _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, psPdmaChann->m_ppsSgtbl[0], u32IdleTimeout_us); + + ret = RT_EOK; + + return ret; + +exit__nu_pdma_transfer_chain: + + _nu_pdma_free_sgtbls(psPdmaChann); + + return -(ret); +} + +rt_err_t nu_pdma_transfer(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, uint32_t u32TransferCnt, uint32_t u32IdleTimeout_us) +{ + rt_err_t ret = RT_EINVAL; + PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID); + nu_pdma_desc_t head; + nu_pdma_chn_t *psPdmaChann; + + nu_pdma_periph_ctl_t *psPeriphCtl = NULL; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_transfer; + else if (!u32TransferCnt) + goto exit_nu_pdma_transfer; + else if (u32TransferCnt > NU_PDMA_MAX_TXCNT) + return _nu_pdma_transfer_chain(i32ChannID, u32DataWidth, u32AddrSrc, u32AddrDst, u32TransferCnt, u32IdleTimeout_us); + + psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos]; + psPeriphCtl = &psPdmaChann->m_spPeripCtl; + + head = &PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)]; + + ret = nu_pdma_desc_setup(i32ChannID, + head, + u32DataWidth, + u32AddrSrc, + u32AddrDst, + u32TransferCnt, + RT_NULL, + 0); + if (ret != RT_EOK) + goto exit_nu_pdma_transfer; + + _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, head, 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; + + 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); +} + +static void nu_pdma_isr(int vector, void *pvdata) +{ + int i; + PDMA_T *PDMA = (void *)pvdata; + + 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 unalignsts = PDMA_GET_ALIGN_STS(PDMA); + uint32_t reqto = intsts & PDMA_INTSTS_REQTOFn_Msk; + uint32_t reqto_ch = (reqto >> PDMA_INTSTS_REQTOF0_Pos); + + int allch_sts = (reqto_ch | tdsts | abtsts | unalignsts); + + // 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); + } + + // Unaligned + if (intsts & PDMA_INTSTS_ALIGNF_Msk) + { + // Clear all Unaligned flags + PDMA_CLR_ALIGN_FLAG(PDMA, unalignsts); + } + + // 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 j = i; + int ch_mask = (1 << i); + + if (PDMA == PDMA1) + { + j += PDMA_CH_MAX; + } + + if (nu_pdma_chn_mask & (1 << j)) + { + int ch_event = 0; + nu_pdma_chn_t *dma_chn = nu_pdma_chn_arr + j - NU_PDMA_CH_Pos; + + if (dma_chn->m_sCB_Event.m_pfnCBHandler) + { + if (abtsts & ch_mask) + { + ch_event |= NU_PDMA_EVENT_ABORT; + } + + if (tdsts & ch_mask) + { + ch_event |= NU_PDMA_EVENT_TRANSFER_DONE; + } + + if (unalignsts & ch_mask) + { + ch_event |= NU_PDMA_EVENT_ALIGNMENT; + } + + if (reqto_ch & ch_mask) + { + PDMA_DisableTimeout(PDMA, ch_mask); + ch_event |= NU_PDMA_EVENT_TIMEOUT; + } + + if (dma_chn->m_sCB_Disable.m_pfnCBHandler) + dma_chn->m_sCB_Disable.m_pfnCBHandler(dma_chn->m_sCB_Disable.m_pvUserData, dma_chn->m_sCB_Disable.m_u32Reserved); + + if (dma_chn->m_u32EventFilter & ch_event) + dma_chn->m_sCB_Event.m_pfnCBHandler(dma_chn->m_sCB_Event.m_pvUserData, ch_event); + + if (reqto_ch & ch_mask) + nu_pdma_timeout_set(j, nu_pdma_chn_arr[j - 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 +} + +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_FIFO); + } +} + +static void nu_pdma_memfun_cb(void *pvUserData, uint32_t u32Events) +{ + rt_err_t result = RT_EOK; + + nu_pdma_memfun_actor_t psMemFunActor = (nu_pdma_memfun_actor_t)pvUserData; + psMemFunActor->m_u32Result = u32Events; + + result = rt_sem_release(psMemFunActor->m_psSemMemFun); + RT_ASSERT(result == RT_EOK); +} + +static int nu_pdma_memfun_employ(void) +{ + int idx = -1 ; + rt_err_t result = 0; + + /* Headhunter */ + if (nu_pdma_memfun_actor_pool_sem && + ((result = 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); + } + RT_ASSERT(result == RT_EOK); + + 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; + struct nu_pdma_chn_cb sChnCB; + rt_err_t result = RT_ERROR; + + int idx; + rt_size_t ret = 0; + + /* Employ actor */ + while ((idx = nu_pdma_memfun_employ()) < 0); + + psMemFunActor = &nu_pdma_memfun_actor_arr[idx]; + + /* Set PDMA memory control to eMemCtl. */ + nu_pdma_channel_memctrl_set(psMemFunActor->m_i32ChannID, eMemCtl); + + /* Register ISR callback function */ + sChnCB.m_eCBType = eCBType_Event; + sChnCB.m_pfnCBHandler = nu_pdma_memfun_cb; + sChnCB.m_pvUserData = (void *)psMemFunActor; + + nu_pdma_filtering_set(psMemFunActor->m_i32ChannID, NU_PDMA_EVENT_ABORT | NU_PDMA_EVENT_TRANSFER_DONE); + nu_pdma_callback_register(psMemFunActor->m_i32ChannID, &sChnCB); + + psMemFunActor->m_u32Result = 0; + + /* Trigger it */ + nu_pdma_transfer(psMemFunActor->m_i32ChannID, + u32DataWidth, + (uint32_t)src, + (uint32_t)dest, + u32TransferCnt, + 0); + + /* Wait it done. */ + result = rt_sem_take(psMemFunActor->m_psSemMemFun, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Give result if get NU_PDMA_EVENT_TRANSFER_DONE.*/ + if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_TRANSFER_DONE) + { + ret += u32TransferCnt; + } + else + { + ret += (u32TransferCnt - 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); + } + + result = rt_mutex_take(nu_pdma_memfun_actor_pool_lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + nu_pdma_memfun_actor_mask &= ~(1 << idx); + + result = rt_mutex_release(nu_pdma_memfun_actor_pool_lock); + RT_ASSERT(result == RT_EOK); + + /* Fire actor */ + result = rt_sem_release(nu_pdma_memfun_actor_pool_sem); + RT_ASSERT(result == RT_EOK); + + 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/nuc980/rtt_port/drv_pdma.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.h new file mode 100644 index 0000000000..8de59ea67e --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.h @@ -0,0 +1,91 @@ +/**************************************************************************//** +* +* @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_PDMA_H__ +#define __DRV_PDMA_H__ + +#include +#include +#include +#include + +#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_ALIGNMENT (1 << 2) +#define NU_PDMA_EVENT_TIMEOUT (1 << 3) +#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 (BOARD_SDRAM_SIZE) +#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); + +typedef enum +{ + eCBType_Event, + eCBType_Trigger, + eCBType_Disable, + eCBType_Undefined = (-1) +} nu_pdma_cbtype_t; + +struct nu_pdma_chn_cb +{ + nu_pdma_cbtype_t m_eCBType; + nu_pdma_cb_handler_t m_pfnCBHandler; + void *m_pvUserData; + uint32_t m_u32Reserved; +}; +typedef struct nu_pdma_chn_cb *nu_pdma_chn_cb_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_chn_cb_t psChnCb); +rt_err_t nu_pdma_transfer(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, uint32_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_cbtype_t eCBType, nu_pdma_chn_cb_t psChnCb_Hijack); +rt_err_t nu_pdma_filtering_set(int i32ChannID, uint32_t u32EventFilter); +uint32_t nu_pdma_filtering_get(int i32ChannID); + +// 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, uint32_t u32BeSilent); +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/nuc980/rtt_port/drv_pwm.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pwm.c new file mode 100644 index 0000000000..f39ec1c70b --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pwm.c @@ -0,0 +1,342 @@ +/**************************************************************************//** +* +* @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 +#if defined(BSP_USING_PWM1) + PWM1_IDX, +#endif + PWM_CNT +}; + +#define NU_PWM_BA_DISTANCE (PWM1_BA - PWM0_BA) +#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 = PWM0_BA, + .rstidx = PWM0RST, + .clkidx = PWM0CKEN, + }, +#endif + +#if defined(BSP_USING_PWM1) + { + .name = "pwm1", + .base_addr = PWM1_BA, + .rstidx = PWM1RST, + .clkidx = PWM1CKEN, + }, +#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_PCLK2) * 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_PCLK2) * 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); + +#if defined(RT_USING_FINSH) + +#include + +#ifdef FINSH_USING_MSH + +static int pwm_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(pwm_get, pwm_get pwm1 1); + +#endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ + +#endif diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_qspi.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_qspi.c new file mode 100644 index 0000000000..96e6110057 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_qspi.c @@ -0,0 +1,400 @@ +/**************************************************************************//** +* +* @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 + +#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, + .rstidx = QSPI0RST, + .clkidx = QSPI0CKEN, + +#if defined(BSP_USING_QSPI_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 +}; /* 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_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; + } + + /* 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, configuration->max_hz); + + 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); +} + +#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 (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 + { + 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) +{ + 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); +#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_sys_ipclk_enable(nu_qspi_arr[i].clkidx); + + nu_sys_ip_reset(nu_qspi_arr[i].rstidx); + + 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; +#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) + { + 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/nuc980/rtt_port/drv_qspi.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_qspi.h new file mode 100644 index 0000000000..87be3e6e42 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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/nuc980/rtt_port/drv_rtc.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c new file mode 100644 index 0000000000..98b3f1b228 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c @@ -0,0 +1,348 @@ +/**************************************************************************//** +* +* @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_RTC) + +#include +#include +#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) +{ + nu_sys_ipclk_enable(RTCCKEN); + + /* 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); + + 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; + + /* 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); + + /* 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 = mktime((struct tm *)&tm_upper); + t_lower = mktime((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 = mktime(&tm_out); + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + + time = (time_t *) args; + tm_in = localtime(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_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 */ +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/nuc980/rtt_port/drv_scuart.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_scuart.c new file mode 100644 index 0000000000..3b08c224e2 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_scuart.c @@ -0,0 +1,336 @@ +/**************************************************************************//** + * + * @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 + +#define BSP_USING_SCUART +#define BSP_USING_SCUART0 + +#if defined(BSP_USING_SCUART) + +#include +#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_SMC0, + .rstidx = SMC0RST, + .clkidx = SMC0CKEN, + }, +#endif + +#if defined(BSP_USING_SCUART1) + { + .name = "scuart1", + .idx = 1, + .irqn = IRQ_SMC1, + .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/nuc980/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c new file mode 100644 index 0000000000..18bfec46f0 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c @@ -0,0 +1,646 @@ +/**************************************************************************//** +* +* @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 +#include +#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 + +#if defined(NU_SDH_USING_PDMA) + #define NU_SDH_MEMCPY nu_pdma_memcpy +#else + #define NU_SDH_MEMCPY memcpy +#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 = SD0CKEN, + .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 = SDHRST, + .clkidx = SD1CKEN, + .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; + unsigned int volatile ier; + 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 */ + NU_SDH_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); + + 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 + + NU_SDH_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; + + rt_event_init(&sdh_event, "sdh_event", RT_IPC_FLAG_FIFO); + + 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]; + + rt_sem_init(&nu_sdh_arr[i].lock, "sdhlock", 1, RT_IPC_FLAG_FIFO); + + 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); + + SDH_Open(nu_sdh_arr[i].base, CardDetect_From_GPIO); + + 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; + DIR *t; + +#if defined(RT_USING_DFS) + + 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++) + { + if (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/nuc980/rtt_port/drv_softi2c.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c new file mode 100644 index 0000000000..d2e08fbb3b --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c @@ -0,0 +1,229 @@ +/**************************************************************************//** +* +* @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 +#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) +{ + nu_systick_udelay(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_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); + 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_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_BOARD_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/nuc980/rtt_port/drv_spi.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_spi.c new file mode 100644 index 0000000000..39e7b7919e --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_spi.c @@ -0,0 +1,639 @@ +/**************************************************************************//** +* +* @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 + +#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 +#if defined(BSP_USING_SPI1) + SPI1_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_event(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, + .rstidx = SPI0RST, + .clkidx = SPI0CKEN, +#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 +#if defined(BSP_USING_SPI1) + { + .name = "spi1", + .spi_base = SPI1, + .rstidx = SPI1RST, + .clkidx = SPI1CKEN, +#if defined(BSP_USING_SPI_PDMA) +#if defined(BSP_USING_SPI1_PDMA) + .pdma_perp_tx = PDMA_SPI1_TX, + .pdma_perp_rx = PDMA_SPI1_RX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + + }, +#endif +}; /* 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; + 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; + } + + /* 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, configuration->max_hz); + + 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_event(void *pvUserData, uint32_t u32EventFilter) +{ + rt_err_t result = RT_EOK; + 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 void nu_pdma_spi_tx_cb_trigger(void *pvUserData, uint32_t u32UserData) +{ + /* Get base address of spi register */ + SPI_T *spi_base = (SPI_T *)pvUserData; + + /* Trigger TX/RX PDMA transfer. */ + SPI_TRIGGER_TX_RX_PDMA(spi_base); +} + +static void nu_pdma_spi_rx_cb_disable(void *pvUserData, uint32_t u32UserData) +{ + /* Get base address of spi register */ + SPI_T *spi_base = (SPI_T *)pvUserData; + + /* Stop TX/RX DMA transfer. */ + SPI_DISABLE_TX_RX_PDMA(spi_base); +} + +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) +{ + struct nu_pdma_chn_cb sChnCB; + + 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; + + nu_pdma_filtering_set(spi_pdma_rx_chid, NU_PDMA_EVENT_TRANSFER_DONE); + + /* Register ISR callback function */ + sChnCB.m_eCBType = eCBType_Event; + sChnCB.m_pfnCBHandler = nu_pdma_spi_rx_cb_event; + sChnCB.m_pvUserData = (void *)spi_bus; + result = nu_pdma_callback_register(spi_pdma_rx_chid, &sChnCB); + if (result != RT_EOK) + { + goto exit_nu_pdma_spi_rx_config; + } + + /* Register Disable engine dma trigger callback function */ + sChnCB.m_eCBType = eCBType_Disable; + sChnCB.m_pfnCBHandler = nu_pdma_spi_rx_cb_disable; + sChnCB.m_pvUserData = (void *)spi_base; + result = nu_pdma_callback_register(spi_pdma_rx_chid, &sChnCB); + 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) +{ + struct nu_pdma_chn_cb sChnCB; + + 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; + } + + /* Register Disable engine dma trigger callback function */ + sChnCB.m_eCBType = eCBType_Trigger; + sChnCB.m_pfnCBHandler = nu_pdma_spi_tx_cb_trigger; + sChnCB.m_pvUserData = (void *)spi_base; + result = nu_pdma_callback_register(spi_pdma_tx_chid, &sChnCB); + if (result != RT_EOK) + { + goto exit_nu_pdma_spi_tx_config; + } + + 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; + + result = nu_pdma_spi_rx_config(spi_bus, recv_addr, length, bytes_per_word); + RT_ASSERT(result == RT_EOK); + + result = nu_pdma_spi_tx_config(spi_bus, send_addr, length, bytes_per_word); + RT_ASSERT(result == RT_EOK); + + /* Wait RX-PDMA transfer done */ + result = rt_sem_take(spi_bus->m_psSemBus, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + 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); + + 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_sys_ipclk_enable(nu_spi_arr[i].clkidx); + + nu_sys_ip_reset(nu_spi_arr[i].rstidx); + + 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/nuc980/rtt_port/drv_spi.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_spi.h new file mode 100644 index 0000000000..30d574528c --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_spi.h @@ -0,0 +1,53 @@ +/**************************************************************************//** +* +* @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_SPI_H__ +#define __DRV_SPI_H__ + +#include + +#include +#include +#include + +#if defined(BSP_USING_SPI_PDMA) + #include +#endif + +struct nu_spi +{ + struct rt_spi_bus dev; + char *name; + SPI_T *spi_base; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + 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/nuc980/rtt_port/drv_sys.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c new file mode 100644 index 0000000000..50271ccfa3 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c @@ -0,0 +1,315 @@ +/**************************************************************************//** +* +* @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 63 +#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); +} + +rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq) +{ + rt_uint32_t active = 0; +#if 0 + rt_uint32_t volatile _mIPER, _mISNR; + + _mIPER = (inpw(REG_AIC_IPER) >> 2) & 0x3f; + _mISNR = inpw(REG_AIC_ISNR); + if ((_mISNR != 0) && (_mIPER == _mISNR)) + active = _mISNR; + +#else + if (fiq_irq != INT_FIQ) + { + active = inpw(REG_AIC_IRQNUM); + } + else + active = inpw(REG_AIC_FIQNUM); +#endif + return active; +} + + +void rt_hw_interrupt_set_priority(int vector, int IntTypeLevel) +{ + rt_uint32_t _mRegAddr; + rt_uint32_t shift; + + if ((vector > SYS_MAX_INT_SOURCE) || (vector < SYS_MIN_INT_SOURCE)) + return; + + _mRegAddr = REG_AIC_SRCCTL0 + ((vector / 4) * 4); + shift = (vector % 4) * 8; + IntTypeLevel &= 0x7; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x07 << shift)) | (IntTypeLevel << shift)); +} + +void rt_hw_interrupt_ack(rt_uint32_t fiq_irq, rt_uint32_t id) +{ + if (fiq_irq != INT_FIQ) + outpw(REG_AIC_EOIS, 1); + else + outpw(REG_AIC_EOFS, 1); +} + +void rt_interrupt_dispatch(rt_uint32_t fiq_irq) +{ + rt_isr_handler_t isr_func; + rt_uint32_t irq; + void *param; + + /* get irq number */ + irq = rt_hw_interrupt_get_active(fiq_irq); + + /* get interrupt service routine */ + isr_func = irq_desc[irq].handler; + param = irq_desc[irq].param; + + /* turn to interrupt service routine */ + isr_func(irq, param); + + rt_hw_interrupt_ack(fiq_irq, irq); +#ifdef RT_USING_INTERRUPT_INFO + irq_desc[irq].counter ++; +#endif +} + +void rt_hw_interrupt_init(void) +{ + int i; + + *((volatile unsigned int *)REG_AIC_INTDIS0) = 0xFFFFFFFF; // disable all interrupt channel + *((volatile unsigned int *)REG_AIC_INTDIS1) = 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 = 1; 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) +{ + rt_uint32_t _mRegAddr; + rt_uint32_t shift; + + if ((vector > SYS_MAX_INT_SOURCE) || (vector < SYS_MIN_INT_SOURCE)) + return ; + + _mRegAddr = REG_AIC_SRCCTL0 + ((vector / 4) * 4); + shift = (vector % 4) * 8; + type &= 0xC0; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0xC0 << shift)) | (type << shift)); +} + +void rt_low_level_init(void) +{ +} + +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(PCLK0CKEN); + nu_sys_ipclk_enable(PCLK1CKEN); + nu_sys_ipclk_enable(SRAMCKEN); + nu_sys_ipclk_enable(SDICCKEN); + nu_sys_ipclk_enable(PCLK2CKEN); + nu_sys_ipclk_enable(PCLKEN0_Reserved_3); +} + +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(); + + // TODO + + while (1); +} + + +void nu_sys_ip_reset(E_SYS_IPRST eIPRstIdx) +{ + uint32_t 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(); + + /* Enable IP reset */ + outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) | (1 << u32IPRSTRegBit)); + + /* Disable IP reset */ + outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) & ~(1 << u32IPRSTRegBit)); + + /* Leave critical section */ + rt_hw_interrupt_enable(level); +} + +static void _nu_sys_ipclk(E_SYS_IPCLK eIPClkIdx, uint32_t bEnable) +{ + uint32_t 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); +} + +#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.); + +#endif + +#endif diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.h new file mode 100644 index 0000000000..f70797e188 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.h @@ -0,0 +1,259 @@ +#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 + + +typedef enum +{ + /* SYS_AHBIPRST, SYS_BA + 0x060 */ + CHIPRST, + AHBIPRST_Reserved_1, + CPURST, + EBIRST, + PDMA0RST, + PDMA1RST, + SDICRST, + GPIORST, + I2SRST, + AHBIPRST_Reserved_9, + VCAP0RST, + VCAP1RST, + AHBIPRST_Reserved_12, + AHBIPRST_Reserved_13, + AHBIPRST_Reserved_14, + AHBIPRST_Reserved_15, + EMAC0RST, + EMAC1RST, + USBHRST, + USBDRST, + FMIRST, + AHBIPRST_Reserved_21, + AHBIPRST_Reserved_22, + CRYPTORST, + SDHRST, + 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, + APBIPRST0_Reserved_3, + AICRST, + APBIPRST0_Reserved_5, + APBIPRST0_Reserved_6, + APBIPRST0_Reserved_7, + TIMER0RST, + TIMER1RST, + TIMER2RST, + TIMER3RST, + TIMER4RST, + TIMER5RST, + APBIPRST0_Reserved_14, + APBIPRST0_Reserved_15, + UART0RST, + UART1RST, + UART2RST, + UART3RST, + UART4RST, + UART5RST, + UART6RST, + UART7RST, + UART8RST, + UART9RST, + APBIPRST0_Reserved_26, + APBIPRST0_Reserved_27, + APBIPRST0_Reserved_28, + APBIPRST0_Reserved_29, + APBIPRST0_Reserved_30, + APBIPRST0_Reserved_31, + + /* SYS_APBIPRST1, SYS_BA + 0x068 */ + I2C0RST, + I2C1RST, + I2C2RST, + I2C3RST, + QSPI0RST, + SPI0RST, + SPI1RST, + APBIPRST1_Reserved_7, + CAN0RST, + CAN1RST, + CAN2RST, + CAN3RST, + 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, + PWM0RST, + PWM1RST, + APBIPRST1_Reserved_28, + APBIPRST1_Reserved_29, + APBIPRST1_Reserved_30, + APBIPRST1_Reserved_31, + + SYS_IPRST_CNT + +} E_SYS_IPRST; + +typedef enum +{ + /* CLK_HCLKEN, CLK_BA + 0x010 */ + CPUCKEN, + HCLKCKEN, + HCLK1CKEN, + HCLK3CKEN, + HCLK4CKEN, + PCLK0CKEN, + PCLK1CKEN, + TICCKEN, + + SRAMCKEN, + EBICKEN, + SDICCKEN, + GPIOCKEN, + PDMA0CKEN, + PDMA1CKEN, + PCLK2CKEN, + CKOCKEN, + + EMAC0CKEN, + EMAC1CKEN, + USBHCKEN, + USBDCKEN, + FMICKEN, + NANDCKEN, + SD0CKEN, + CRYPTOCKEN, + + I2SCKEN, + HCLKEN_Reserved_25, + VCAP0CKEN, + SENSORCKEN, + HCLKEN_Reserved_28, + HCLKEN_Reserved_29, + SD1CKEN, + VCAP1CKEN, + + CLK_HCLKEN_END, + + /* CLK_BA+0x014 */ + + /* CLK_PCLKEN0 CLK_BA+0x018 */ + CLK_PCLKEN0_BEGIN = CLK_HCLKEN_END + 32, + + WDTCKEN = CLK_PCLKEN0_BEGIN, + WWDTCKEN, + RTCCKEN, + PCLKEN0_Reserved_3, + PCLKEN0_Reserved_4, + PCLKEN0_Reserved_5, + PCLKEN0_Reserved_6, + PCLKEN0_Reserved_7, + + TIMER0CKEN, + TIMER1CKEN, + TIMER2CKEN, + TIMER3CKEN, + TIMER4CKEN, + TIMER5CKEN, + PCLKEN0_Reserved_14, + PCLKEN0_Reserved_15, + + UART0CKEN, + UART1CKEN, + UART2CKEN, + UART3CKEN, + UART4CKEN, + UART5CKEN, + UART6CKEN, + UART7CKEN, + + UART8CKEN, + UART9CKEN, + PCLKEN0_Reserved_26, + PCLKEN0_Reserved_27, + PCLKEN0_Reserved_28, + PCLKEN0_Reserved_29, + PCLKEN0_Reserved_30, + PCLKEN0_Reserved_31, + + /* CLK_PCLKEN1, CLK_BA + 0x01C */ + I2C0CKEN, + I2C1CKEN, + I2C2CKEN, + I2C3CKEN, + QSPI0CKEN, + SPI0CKEN, + SPI1CKEN, + PCLKEN1_Reserved_7, + + CAN0CKEN, + CAN1CKEN, + CAN2CKEN, + CAN3CKEN, + 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, + PWM0CKEN, + PWM1CKEN, + PCLKEN1_Reserved_28, + PCLKEN1_Reserved_29, + PCLKEN1_Reserved_30, + PCLKEN1_Reserved_31, + + SYS_IPCLK_CNT + +} E_SYS_IPCLK; + +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); + +#endif diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_systick.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_systick.c new file mode 100644 index 0000000000..0060ec37a9 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_systick.c @@ -0,0 +1,86 @@ +/**************************************************************************//** +* +* @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" + +#define USE_TIMER 5 + +/* Concatenate */ +#define _CONCAT2_(x, y) x##y +#define CONCAT2(x, y) _CONCAT2_(x, y) + +/* Concatenate the macros of timer instance for driver usage. */ +#define SYSTICK CONCAT2(TIMER, USE_TIMER) +#define SYSTICK_IRQ CONCAT2(IRQ_TIMER, USE_TIMER) + +static void nu_systick_isr(int vector, void *param) +{ + rt_tick_increase(); + ETIMER_ClearIntFlag(USE_TIMER); +} + +void rt_hw_systick_init(void) +{ + nu_sys_ipclk_enable(TIMER5CKEN); + + nu_sys_ip_reset(TIMER5RST); + + // Set timer frequency + ETIMER_Open(USE_TIMER, ETIMER_PERIODIC_MODE, RT_TICK_PER_SECOND); + + // Enable timer interrupt + ETIMER_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); + + ETIMER_Start(USE_TIMER); +} /* rt_hw_systick_init */ + +void nu_systick_udelay(uint32_t delay_us) +{ + rt_uint32_t ticks; + rt_uint32_t told, tnow, tcnt = 0; + rt_uint32_t cmp = ETIMER_GetCompareData(USE_TIMER); + + ticks = delay_us * cmp / (1000000 / RT_TICK_PER_SECOND); + told = ETIMER_GetCounter(USE_TIMER); + while (1) + { + /* Timer counter is increment. */ + tnow = ETIMER_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; + } + } + } + +} /* nu_systick_udelay */ diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uart.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uart.c new file mode 100644 index 0000000000..ba211aa746 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uart.c @@ -0,0 +1,864 @@ +/**************************************************************************//** +* +* @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_UART) + +#include +#include +#include +#include +#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 +#if defined(BSP_USING_UART8) + UART8_IDX, +#endif +#if defined(BSP_USING_UART9) + UART9_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; +#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; + + nu_pdma_desc_t pdma_rx_desc; + +#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); + +#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, + .irqn = IRQ_UART0, + .rstidx = UART0RST, + .clkidx = UART0CKEN, + +#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, + .irqn = IRQ_UART1, + .rstidx = UART1RST, + .clkidx = UART1CKEN, + +#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, + .irqn = IRQ_UART2, + .rstidx = UART2RST, + .clkidx = UART2CKEN, + +#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, + .irqn = IRQ_UART3, + .rstidx = UART3RST, + .clkidx = UART3CKEN, + +#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, + .irqn = IRQ_UART4, + .rstidx = UART4RST, + .clkidx = UART4CKEN, + +#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, + .irqn = IRQ_UART5, + .rstidx = UART5RST, + .clkidx = UART5CKEN, + +#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, + .irqn = IRQ_UART6, + .rstidx = UART6RST, + .clkidx = UART6CKEN, + +#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, + .irqn = IRQ_UART7, + .rstidx = UART7RST, + .clkidx = UART7CKEN, + +#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 + +#if defined(BSP_USING_UART8) + { + .name = "uart8", + .uart_base = UART8, + .irqn = IRQ_UART8, + .rstidx = UART8RST, + .clkidx = UART8CKEN, + +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART8_TX_DMA) + .pdma_perp_tx = PDMA_UART8_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART8_RX_DMA) + .pdma_perp_rx = PDMA_UART8_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART9) + { + .name = "uart9", + .uart_base = UART9, + .irqn = IRQ_UART9, + .rstidx = UART9RST, + .clkidx = UART9CKEN, + +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART9_TX_DMA) + .pdma_perp_tx = PDMA_UART9_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART9_RX_DMA) + .pdma_perp_rx = PDMA_UART9_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#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; + +#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; + } + + 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); +} + +#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; + struct nu_pdma_chn_cb sChnCB; + nu_uart_t psNuUart = (nu_uart_t)serial; + + /* Get base address of uart register */ + UART_T *uart_base = psNuUart->uart_base; + + /* Register ISR callback function */ + sChnCB.m_eCBType = eCBType_Event; + sChnCB.m_pfnCBHandler = nu_pdma_uart_rx_cb; + sChnCB.m_pvUserData = (void *)serial; + + nu_pdma_filtering_set(psNuUart->pdma_chanid_rx, NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT); + result = nu_pdma_callback_register(psNuUart->pdma_chanid_rx, &sChnCB); + + if (result != RT_EOK) + { + goto exit_nu_pdma_uart_rx_config; + } + + if (serial->config.bufsz == 0) + { + 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; + } + } + else + { + /* For Serial RX FIFO - Single buffer recycle SG trigger */ + /* Link to next */ + nu_pdma_desc_t next = psNuUart->pdma_rx_desc; + + result = nu_pdma_desc_setup(psNuUart->pdma_chanid_rx, + psNuUart->pdma_rx_desc, + 8, + (uint32_t)uart_base, + (uint32_t)pu8Buf, + i32TriggerLen, + next, + 0); + if (result != RT_EOK) + { + goto exit_nu_pdma_uart_rx_config; + } + + /* Assign head descriptor & go */ + result = nu_pdma_sg_transfer(psNuUart->pdma_chanid_rx, psNuUart->pdma_rx_desc, 1000); + 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_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); + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + + /* 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) + { + 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; + +#if defined(BSP_USING_MMU) + mmu_invalidate_dcache((uint32_t)&rx_fifo->buffer[puart->rx_write_offset], recv_len); +#endif + + 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) +{ + struct nu_pdma_chn_cb sChnCB; + RT_ASSERT(serial != RT_NULL); + + /* Register ISR callback function */ + sChnCB.m_eCBType = eCBType_Event; + sChnCB.m_pfnCBHandler = nu_pdma_uart_tx_cb; + sChnCB.m_pvUserData = (void *)serial; + + nu_pdma_filtering_set(((nu_uart_t)serial)->pdma_chanid_tx, NU_PDMA_EVENT_TRANSFER_DONE); + return nu_pdma_callback_register(((nu_uart_t)serial)->pdma_chanid_tx, &sChnCB); +} + +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; + nu_uart_t psNuUart = (nu_uart_t)serial; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = psNuUart->uart_base; + if (direction == RT_SERIAL_DMA_TX) + { + result = nu_pdma_transfer(psNuUart->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_INTEN_RXPDMAEN_Msk); // Start DMA TX transfer + + // If config.bufsz = 0, serial will trigger once. + psNuUart->rxdma_trigger_len = size; + psNuUart->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) + { + rt_err_t ret = RT_EOK; + pusrt->dma_flag |= RT_DEVICE_FLAG_DMA_RX; + ret = nu_pdma_sgtbls_allocate(&pusrt->pdma_rx_desc, 1); + RT_ASSERT(ret == RT_EOK); + } + } + + return RT_EOK; +} +#endif + +/** + * 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_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(psNuUart->pdma_chanid_rx); + UART_DISABLE_INT(uart_base, UART_INTEN_RLSIEN_Msk | 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; + psNuUart->rxdma_trigger_len = serial->config.bufsz; + psNuUart->rx_write_offset = 0; + + result = nu_pdma_uart_rx_config(serial, &rx_fifo->buffer[0], psNuUart->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 interrupt. */ + rt_hw_interrupt_mask(psNuUart->irqn); + +#if defined(RT_SERIAL_USING_DMA) + nu_pdma_channel_terminate(psNuUart->pdma_chanid_tx); + nu_pdma_channel_terminate(psNuUart->pdma_chanid_rx); +#endif + + /* 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 + + 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/nuc980/rtt_port/drv_uart.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uart.h new file mode 100644 index 0000000000..2596c9be0a --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/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/nuc980/rtt_port/drv_wdt.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_wdt.c new file mode 100644 index 0000000000..5564c5885d --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_wdt.c @@ -0,0 +1,411 @@ +/**************************************************************************//** +* +* @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 +#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); + +#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: + + outpw(REG_WDT_CTL, inpw(REG_WDT_CTL) & ~(1 << 7)); + 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: + + outpw(REG_WDT_CTL, inpw(REG_WDT_CTL) | (1 << 7)); + break; + + default: + break; + } +} + + +/* device pm frequency_change() entry. */ +static int wdt_pm_frequency_change(const struct rt_device *device, rt_uint8_t mode) +{ + 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) +{ + nu_sys_ipclk_enable(WDTCKEN); + + SYS_UnlockReg(); + + if (WDT_GET_RESET_FLAG()) + { + LOG_W("System re-boots from watchdog timer reset.\n"); + WDT_CLEAR_RESET_FLAG(); + } + + SYS_LockReg(); + + 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); + +#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); + + return RT_EOK; +} + + +static uint32_t wdt_get_working_hz(void) +{ + static uint32_t u32ClkTbl[4] = {12000000, 12000000 / 512, 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/512 Hz + case 3: // 32.768 Hz + clk = u32ClkTbl[u32WDT_S]; + break; + + case 2: // PCLK2/4096 Hz + clk = sysGetClock(SYS_PCLK2) * 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; + + 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 */ +static void nu_wdt_isr(int vector, void *param) +{ + /* 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; + } + } +} + +#endif /* BSP_USING_WDT */ + + diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config new file mode 100644 index 0000000000..2892d877bd --- /dev/null +++ b/bsp/nuvoton/nk-980iot/.config @@ -0,0 +1,817 @@ +# +# 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=8 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=8 +CONFIG_DFS_FD_MAX=64 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +CONFIG_RT_USING_DFS_ELMFAT=y + +# +# elm-chan's FatFs, Generic FAT Filesystem Module +# +CONFIG_RT_DFS_ELM_CODE_PAGE=437 +CONFIG_RT_DFS_ELM_WORD_ACCESS=y +# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set +CONFIG_RT_DFS_ELM_USE_LFN_3=y +CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_MAX_LFN=255 +CONFIG_RT_DFS_ELM_DRIVES=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 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_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 + +# +# 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 + +# +# 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 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_ILI9341 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=4 +CONFIG_NU_PDMA_SGTBL_POOL_SIZE=16 +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 is not set +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 is not set +# 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 is not set +CONFIG_BSP_USING_QSPI=y +CONFIG_BSP_USING_QSPI0=y +# CONFIG_BSP_USING_QSPI0_PDMA is not set +# 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 is not set +# CONFIG_BSP_USING_HSUSBD is not set +# CONFIG_BSP_USING_USBH is not set +# CONFIG_BSP_USING_HSUSBH is not set +# CONFIG_BSP_USING_HSOTG is not set + +# +# On-board Peripheral Drivers +# +CONFIG_BSP_USING_CONSOLE=y +CONFIG_BOARD_USING_IP101GR=y +# CONFIG_BOARD_USING_NAU8822L is not set +CONFIG_BOARD_USING_STORAGE_SDCARD=y +CONFIG_BOARD_USING_STORAGE_SPIFLASH=y +CONFIG_BOARD_USING_USB_NONE=y +# CONFIG_BOARD_USING_HSUSBD is not set +# CONFIG_BOARD_USING_HSUSBD_USBH is not set +# CONFIG_BOARD_USING_HSUSBH is not set +# CONFIG_BOARD_USING_HSUSBH_USBD is not set +# CONFIG_BOARD_USING_HSOTG is not set + +# +# 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." diff --git a/bsp/nuvoton/nk-980iot/Kconfig b/bsp/nuvoton/nk-980iot/Kconfig new file mode 100644 index 0000000000..5c55e87c61 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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-980iot/README.md b/bsp/nuvoton/nk-980iot/README.md new file mode 100644 index 0000000000..28621d8010 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/README.md @@ -0,0 +1,102 @@ +# NK-980IoT +## 1. Introduction +Nuvoton Technology provides industrial IoT development platform using NUC980DK61Y microprocessor, which is an industrial IoT open platform, including complete hardware design and software reference design. The platform is powered by Nuvoton ARM9 MPU with a 300 MHz internal speed and up to 128 MB DDR memory, single 10/100 Ethernet port, 2 high-speed USB hosts, 1 Gb SPI NAND Flash memory, microphone input, stereo headphone output and Arduino compatible interface. The platform supports embedded Linux OS which provides all IoT protocols you need, users can use this platform to quickly develop a plenty of IoT applications. + +[![NK-980IOT](https://i.imgur.com/bKvBJLA.png "NK-980IOT")](https://i.imgur.com/bKvBJLA.png "NK-980IOT") + + +### 1.1 MCU specification + +| | Features | +| -- | -- | +| Part NO. | NUC980DK61Y | +| MCU ARCH. | 32-bit ARM926EJ-STM | +| Operation frequency | 300 MHz | +| Embedded SDRAM size | Built-in 64MB (Up to 128 MB DDR memory) | +| Crypto engine | AES, RSA, ECC, HMAC and SHA crypto accelerator | +| RMII interface | 10/100 Mbps x2 | +| USB 2.0 | High Speed Host x1, High Speed Host/Device x1 | +| Audio | Mono microphone / Stereo headphone | +| Extern storage | 1 Gbit SPI-NAND Flash | +| SD card slot | SD | +| EBI interface | External memory expansion interface | + +### 1.2 Interface + +| Interface | +| -- | +| Arduino UNO | +| A RJ45 Ethernet | +| An USB 2.0 HS port | +| An USB 2.0 HS OTG port | +| A microSD slot | +| A 3.5mm Audio connector | +| An EBI connector | +| An ICE connector | + +### 1.3 On-board devices + +| Device | Description | Driver supporting status | +| -- | -- | -- | +|Ethernet PHY | IP101GR | Supported | +|Button | | Supported | +|LEDs | | Supported | +|Audio Codec | NAU88L22, Supports MIC and earphone | Not ready | +|SPI NAND flash | W25Q32 | Not ready | +|Virtual COM | For console | Need to install virtual com port driver. | + +## 2. Supported compiler +Support GCC, MDK4 and MDK5 IDE/compilers. More information of these compiler version as following: + +| IDE/Compiler | Tested version | +| ---------- | ---------------------------- | +| MDK4 | 4.76 | +| 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/NvbzsRp.gif "SDRAM Downloading using NuWriter")](https://i.imgur.com/NvbzsRp.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
+
+ +### 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/8OtXGSQ.gif "SPI NOR flash")](https://i.imgur.com/8OtXGSQ.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 >>
+
+ +## 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][1] + +## 6. Resources +* [Download board schematics][2] +* [Download NK-980IOT Quick Start Guide][3] +* [Download MCU TRM][4] +* [Download NuWriter][5] + + [1]: https://direct.nuvoton.com/tw/numaker-iiot-nuc980 + [2]: https://www.nuvoton.com/resource-download.jsp?tp_GUID=UG1020190308162722 + [3]: http://www.nuvoton.com/resource-download.jsp?tp_GUID=UG0520190311115040 + [4]: https://www.nuvoton.com/resource-download.jsp?tp_GUID=DA05-NUC980-1 + [5]: https://github.com/OpenNuvoton/NUC980_NuWriter + \ No newline at end of file diff --git a/bsp/nuvoton/nk-980iot/SConscript b/bsp/nuvoton/nk-980iot/SConscript new file mode 100644 index 0000000000..fe0ae941ae --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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-980iot/SConstruct b/bsp/nuvoton/nk-980iot/SConstruct new file mode 100644 index 0000000000..4290749228 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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 = 'nuc980' +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-980iot/applications/SConscript b/bsp/nuvoton/nk-980iot/applications/SConscript new file mode 100644 index 0000000000..9ffdbcd0f9 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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-980iot/applications/main.c b/bsp/nuvoton/nk-980iot/applications/main.c new file mode 100644 index 0000000000..fc076010b1 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/applications/main.c @@ -0,0 +1,84 @@ +/**************************************************************************//** +* +* @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 LED_R pin: PB13 */ +#define LED_R NU_GET_PININDEX(NU_PB, 13) + +/* defined the LED_Y pin: PB8 */ +#define LED_Y NU_GET_PININDEX(NU_PB, 8) + +/* defined the Key1 pin: PE10 */ +#define KEY_1 NU_GET_PININDEX(NU_PE, 10) + +/* defined the Key2 pin: PE12 */ +#define KEY_2 NU_GET_PININDEX(NU_PE, 12) + +static uint32_t u32Key1 = KEY_1; +static uint32_t u32Key2 = KEY_2; + +void nu_button_cb(void *args) +{ + uint32_t u32Key = *((uint32_t *)(args)); + + switch (u32Key) + { + case KEY_1: + rt_pin_write(LED_Y, PIN_HIGH); + break; + case KEY_2: + rt_pin_write(LED_Y, PIN_LOW); + break; + } +} +#endif + +int main(int argc, char **argv) +{ +#if defined(RT_USING_PIN) + int counter = 1000; + + /* set LED_R pin mode to output */ + rt_pin_mode(LED_R, PIN_MODE_OUTPUT); + + /* set LED_Y pin mode to output */ + rt_pin_mode(LED_Y, PIN_MODE_OUTPUT); + + /* set KEY_1 pin mode to input */ + rt_pin_mode(KEY_1, PIN_MODE_INPUT_PULLUP); + + /* set KEY_2 pin mode to output */ + rt_pin_mode(KEY_2, PIN_MODE_INPUT_PULLUP); + + rt_pin_attach_irq(KEY_1, PIN_IRQ_MODE_FALLING, nu_button_cb, &u32Key1); + rt_pin_irq_enable(KEY_1, PIN_IRQ_ENABLE); + + rt_pin_attach_irq(KEY_2, PIN_IRQ_MODE_FALLING, nu_button_cb, &u32Key2); + rt_pin_irq_enable(KEY_2, PIN_IRQ_ENABLE); + + while (counter--) + { + rt_pin_write(LED_R, PIN_HIGH); + rt_thread_mdelay(100); + rt_pin_write(LED_R, PIN_LOW); + rt_thread_mdelay(100); + } + +#endif + + return 0; +} diff --git a/bsp/nuvoton/nk-980iot/applications/mnt.c b/bsp/nuvoton/nk-980iot/applications/mnt.c new file mode 100644 index 0000000000..f084c1d15e --- /dev/null +++ b/bsp/nuvoton/nk-980iot/applications/mnt.c @@ -0,0 +1,190 @@ +/**************************************************************************//** +* +* @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 MOUNT_POINT_RAMDISK0 "/" +#endif + +#if defined(BOARD_USING_STORAGE_SPIFLASH) + #define PARTITION_NAME_FILESYSTEM "filesystem" + #define MOUNT_POINT_SPIFLASH0 "/mnt/"PARTITION_NAME_FILESYSTEM +#endif + +#if defined(PKG_USING_RAMDISK) + +/* 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) +{ + // ramdisk as root + if (rt_device_find(RAMDISK_NAME)) + { + // format the ramdisk + dfs_mkfs("elm", RAMDISK_NAME); + + /* 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); +#if defined(RT_USBH_MSTORAGE) && defined(UDISK_MOUNTPOINT) + mkdir_p(UDISK_MOUNTPOINT, 0x777); +#endif + } + else + { + LOG_E("root folder creation failed!\n"); + } + return RT_EOK; + } + LOG_E("cannot find %s device", RAMDISK_NAME); + return -RT_ERROR; +} +INIT_ENV_EXPORT(filesystem_init); + +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) +{ + /* Create a 16MB RAMDISK */ + return (int)ramdisk_init(RAMDISK_NAME, NULL, 512, 2048 * 4); +} +INIT_DEVICE_EXPORT(ramdisk_device_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-980iot/board/Kconfig b/bsp/nuvoton/nk-980iot/board/Kconfig new file mode 100644 index 0000000000..6fa2cc6065 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/board/Kconfig @@ -0,0 +1,133 @@ +menu "Hardware Drivers Config" + + menu "On-chip Peripheral Drivers" + source "$BSP_DIR/../libraries/nuc980/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 + default n + + + config BOARD_USING_NAU8822L + bool "NAU8822L Audio Codec supporting(over i2s, i2c2)" + select NU_PKG_USING_NAU8822L + 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 + + choice + prompt "Select FS/HS USB Ports" + + config BOARD_USING_USB_NONE + bool "Without any USB function" + help + Choose this option if you need not USB functions. + + config BOARD_USING_HSUSBD + select BSP_USING_HSUSBD + bool "Enable HSUSBD(over USB2.0)" + help + Choose this option if you need HSUSBD function mode. + + config BOARD_USING_HSUSBD_USBH + select BSP_USING_USBH + select BSP_USING_HSUSBD + bool "Enable HSUSBD(over USB2.0) and USBH(over USB1.1)" + help + Choose this option if you need HSUSBD and USBH function mode at the same time. + + config BOARD_USING_HSUSBH + select BSP_USING_HSUSBH + bool "Enable HSUSBH(over USB2.0)" + help + Choose this option if you need HSUSBH function mode. + + config BOARD_USING_HSUSBH_USBD + select BSP_USING_HSUSBH + select BSP_USING_USBD + bool "Enable HSUSBH(over USB2.0) and USBD(over USB1.1)" + help + Choose this option if you need HSUSBH and USBD function mode at the same time. + + config BOARD_USING_HSOTG + select BSP_USING_HSOTG + bool "Enable HSOTG(over USB2.0)" + help + Choose this option if you need HSOTG function mode. + + endchoice + + endmenu + + menu "Board extended module drivers" + + config BOARD_USING_MAX31875 + bool "MAX31875 Temperature sensor(over i2c1)" + select NU_PKG_USING_MAX31875 + select BSP_USING_I2C1 + default n + + config BOARD_USING_LCD_ILI9341 + bool "LCD ILI9341 (over spi0)" + select NU_PKG_USING_ILI9341 + select NU_PKG_USING_ILI9341_SPI + select BSP_USING_SPI0 + default n + + if BOARD_USING_LCD_ILI9341 + + config BOARD_USING_ILI9341_PIN_BACKLIGHT + int "Specify the pin index of backlight pin index" + range 0 127 + default 103 + + config BOARD_USING_ILI9341_PIN_RESET + int "Specify the pin index of reset pin index" + range 0 127 + default 90 + + config BOARD_USING_ILI9341_PIN_DC + int "Specify the pin index of data&command switching" + range 0 127 + default 89 + + endif + + config BOARD_USING_ESP8266 + bool "ESP8266 Wi-Fi module supporting(over uart1)" + select BSP_USING_UART + select BSP_USING_UART1 + select BSP_USING_UART1_RX_DMA + select BSP_USING_UART1_TX_DMA + select PKG_USING_AT_DEVICE + select AT_DEVICE_USING_ESP8266 + select AT_DEVICE_ESP8266_INIT_ASYN + default n + + endmenu + + +endmenu diff --git a/bsp/nuvoton/nk-980iot/board/SConscript b/bsp/nuvoton/nk-980iot/board/SConscript new file mode 100644 index 0000000000..3f8e1c167f --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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-980iot/board/board.h b/bsp/nuvoton/nk-980iot/board/board.h new file mode 100644 index 0000000000..f5392785a3 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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 +#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-980iot/board/board_dev.c b/bsp/nuvoton/nk-980iot/board/board_dev.c new file mode 100644 index 0000000000..35a6d58bd2 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/board/board_dev.c @@ -0,0 +1,218 @@ +/**************************************************************************//** +* +* @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 +#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_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS; + rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1); + + return u8Val; +} + +static rt_uint8_t SpiFlash_ReadStatusReg2(struct rt_qspi_device *qspi_device) +{ + rt_uint8_t u8Val; + rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS2; + rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1); + + return u8Val; +} + +static void SpiFlash_WriteStatusReg(struct rt_qspi_device *qspi_device, uint8_t u8Value1, uint8_t u8Value2) +{ + rt_uint8_t w25x_txCMD1; + rt_uint8_t u8Val[3]; + + w25x_txCMD1 = W25X_REG_WRITEENABLE; + rt_qspi_send(qspi_device, &w25x_txCMD1, 1); + + u8Val[0] = W25X_REG_WRITESTATUS; + u8Val[1] = u8Value1; + u8Val[2] = u8Value2; + rt_qspi_send(qspi_device, &u8Val, 3); +} + +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) +{ + uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device); + uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device); + + u8Status2 |= W25X_REG_QUADENABLE; + SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2); + SpiFlash_WaitReady(qspi_device); +} + +static void SpiFlash_ExitQspiMode(struct rt_qspi_device *qspi_device) +{ + uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device); + uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device); + + u8Status2 &= ~W25X_REG_QUADENABLE; + SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2); + 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", 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_LCD_ILI9341) && defined(NU_PKG_USING_ILI9341_SPI) +#include +#if defined(PKG_USING_GUIENGINE) + #include +#endif +int rt_hw_ili9341_port(void) +{ + if (rt_hw_lcd_ili9341_spi_init("spi0") != RT_EOK) + return -1; + + rt_hw_lcd_ili9341_init(); + +#if defined(PKG_USING_GUIENGINE) + rt_device_t lcd_ili9341; + lcd_ili9341 = rt_device_find("lcd"); + if (lcd_ili9341) + { + rtgui_graphic_set_device(lcd_ili9341); + } +#endif + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_ili9341_port); +#endif /* BOARD_USING_LCD_ILI9341 */ + + +#if defined(BOARD_USING_ESP8266) +#include + +#define LOG_TAG "at.sample.esp" +#undef DBG_TAG +#undef DBG_LVL +#include + +static struct at_device_esp8266 esp0 = +{ + "esp0", /* esp8266 device name */ + "uart1", /* esp8266 serial device name, EX: uart1, uuart1 */ + + "NT_ZY_BUFFALO", /* Wi-Fi SSID */ + "12345678", /* Wi-Fi PASSWORD */ + 2048 /* Receive buffer length */ +}; + +static int rt_hw_esp8266_port(void) +{ + struct at_device_esp8266 *esp8266 = &esp0; + + return at_device_register(&(esp8266->device), + esp8266->device_name, + esp8266->client_name, + AT_DEVICE_CLASS_ESP8266, + (void *) esp8266); +} +//INIT_APP_EXPORT(rt_hw_esp8266_port); + +static void at_wifi_set(int argc, char **argv) +{ + struct at_device_ssid_pwd sATDConf; + struct at_device *at_dev = RT_NULL; + + /* If the number of arguments less than 2 */ + if (argc != 3) + { + rt_kprintf("\n"); + rt_kprintf("at_wifi_set \n"); + return ; + } + + sATDConf.ssid = argv[1]; //ssid + sATDConf.password = argv[2]; //password + + if ((at_dev = at_device_get_first_initialized()) != RT_NULL) + at_device_control(at_dev, AT_DEVICE_CTRL_SET_WIFI_INFO, &sATDConf); + else + { + rt_kprintf("Can't find any initialized AT device.\n"); + } +} +#ifdef FINSH_USING_MSH + MSH_CMD_EXPORT(at_wifi_set, AT device wifi set ssid / password function); +#endif +#endif /* BOARD_USING_ESP8266 */ + + +#if defined(BOARD_USING_NAU88L25) && defined(NU_PKG_USING_NAU88L25) +#include +S_NU_NAU88L25_CONFIG sCodecConfig = +{ + .i2c_bus_name = "i2c0", + + .i2s_bus_name = "sound0", + + .pin_phonejack_en = NU_GET_PININDEX(NU_PE, 13), + + .pin_phonejack_det = 0, +}; + +int rt_hw_nau88l25_port(void) +{ + if (nu_hw_nau88l25_init(&sCodecConfig) != RT_EOK) + return -1; + + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_nau88l25_port); +#endif /* BOARD_USING_NAU88L25 */ diff --git a/bsp/nuvoton/nk-980iot/board/fal_cfg.h b/bsp/nuvoton/nk-980iot/board/fal_cfg.h new file mode 100644 index 0000000000..a8ff4ecd86 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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-980iot/board/nu_pin_init.c b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c new file mode 100644 index 0000000000..4177e03b82 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c @@ -0,0 +1,97 @@ +/**************************************************************************//** +* +* @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: GPF11, GPF12 */ + outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & 0xfff00fff) | 0x11000); + + /* UART1: GPF9, GPF10 */ + outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & 0xfffff00f) | 0x00220); +} + +static void nu_pin_emac_init(void) +{ + /* EMAC0 */ + outpw(REG_SYS_GPE_MFPL, 0x11111111); + outpw(REG_SYS_GPE_MFPH, (inpw(REG_SYS_GPE_MFPH) & ~0xFF) | 0x11); + + /* EMAC1 */ +// outpw(REG_SYS_GPF_MFPL, 0x11111111); +// outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & ~0xFF) | 0x11); +} + +static void nu_pin_sdh_init(void) +{ + /* SDH1: PF[0, 6] */ + outpw(REG_SYS_GPF_MFPL, (inpw(REG_SYS_GPF_MFPL) & ~0x0FFFFFFF) | 0x02222222); +} + +static void nu_pin_qspi_init(void) +{ + /* QSPI0: PD[2, 7] */ + outpw(REG_SYS_GPD_MFPL, (inpw(REG_SYS_GPD_MFPL) & ~0xFFFFFF00) | 0x11111100); +} + +static void nu_pin_spi_init(void) +{ + /* SPI0: PD[8, 11] */ + outpw(REG_SYS_GPD_MFPH, (inpw(REG_SYS_GPD_MFPH) & ~0x0000FFFF) | 0x00001111); +} + +static void nu_pin_i2c_init(void) +{ + /* I2C0: PA[0, 1] */ + outpw(REG_SYS_GPA_MFPL, (inpw(REG_SYS_GPA_MFPL) & ~0x000000FF) | 0x00000033); + + /* I2C2: PB5, PB7 */ + outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & ~0xF0F00000) | 0x20200000); +} + + +static void nu_pin_pwm_init(void) +{ + /* PWM02, PWM03: PF[7, 8] */ + outpw(REG_SYS_GPF_MFPL, (inpw(REG_SYS_GPF_MFPL) & ~0xF0000000) | 0x40000000); + outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & ~0x0000000F) | 0x00000004); +} + +static void nu_pin_i2s_init(void) +{ + /* I2S A[2, 6] */ + outpw(REG_SYS_GPA_MFPL, (inpw(REG_SYS_GPA_MFPL) & ~0x0FFFFF00) | 0x02222200); +} + +static void nu_pin_can_init(void) +{ + +} + +void nu_pin_init(void) +{ + nu_pin_uart_init(); + nu_pin_emac_init(); + nu_pin_sdh_init(); + nu_pin_qspi_init(); + nu_pin_spi_init(); + nu_pin_i2c_init(); + nu_pin_pwm_init(); + nu_pin_i2s_init(); + nu_pin_can_init(); +} + +void nu_pin_deinit(void) +{ + +} diff --git a/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld b/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld new file mode 100644 index 0000000000..19699374b8 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld @@ -0,0 +1,114 @@ +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); + __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 = .; + 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); + .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-980iot/linking_scripts/nuc980.sct b/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.sct new file mode 100644 index 0000000000..114b346e8c --- /dev/null +++ b/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.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-980iot/rtconfig.py b/bsp/nuvoton/nk-980iot/rtconfig.py new file mode 100644 index 0000000000..df4a99bcee --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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_nuc980.map' +LINK_FILE = 'linking_scripts/nuc980' +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-980iot/template.uvproj b/bsp/nuvoton/nk-980iot/template.uvproj new file mode 100644 index 0000000000..23e8dd2bcb --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + + + 1 + 0 + 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\nuc980.sct + + + + + + + + + + + +
diff --git a/bsp/nuvoton/nk-980iot/template.uvprojx b/bsp/nuvoton/nk-980iot/template.uvprojx new file mode 100644 index 0000000000..aad158ccc3 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/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\nuc980.sct + + + + + + + + + + + + + + + + + +
diff --git a/bsp/nuvoton/numaker-iot-m487/.config b/bsp/nuvoton/numaker-iot-m487/.config index 4b62955898..a828d7042d 100644 --- a/bsp/nuvoton/numaker-iot-m487/.config +++ b/bsp/nuvoton/numaker-iot-m487/.config @@ -19,7 +19,7 @@ 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_IDLE_THREAD_STACK_SIZE=1024 # CONFIG_RT_USING_TIMER_SOFT is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y diff --git a/bsp/nuvoton/numaker-iot-m487/Nu_Link_Driver.ini b/bsp/nuvoton/numaker-iot-m487/Nu_Link_Driver.ini index a05c057411..8e9352bcef 100644 --- a/bsp/nuvoton/numaker-iot-m487/Nu_Link_Driver.ini +++ b/bsp/nuvoton/numaker-iot-m487/Nu_Link_Driver.ini @@ -1,5 +1,5 @@ [Version] -Nu_LinkVersion=V5.13 +Nu_LinkVersion=V5.14 [Process] ProcessID=0x00003a80 ProcessCreationTime_L=0xac7abbce @@ -1017,3 +1017,20 @@ MemAccessWhileRun=0 RAMForAlgorithmStart=0x20000000 RAMForAlgorithmSize=0x1000 ProgramAlgorithm=NM1240_AP_64.FLM +[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 diff --git a/bsp/nuvoton/numaker-iot-m487/README.md b/bsp/nuvoton/numaker-iot-m487/README.md index 480c536936..0e4fad21dd 100644 --- a/bsp/nuvoton/numaker-iot-m487/README.md +++ b/bsp/nuvoton/numaker-iot-m487/README.md @@ -17,19 +17,19 @@ NuMaker-IoT-M487 provides multiple networking, interfaces, audio recording, play ### 1.2 Interface -| Interface | +| Interface | | -- | | Arduino UNO | | mikroBUS | | NuMaker-Brick I2C | -| RJ45 Ethernet | +| RJ45 Ethernet | | USB 1.1/2.0 OTG ports | | A microSD slot | | A 3.5mm Audio connector | ### 1.3 On-board devices -| Device | Descirption | Driver supporting status | +| Device | Description | Driver supporting status | | -- | -- | -- | |SPI flash | W25Q32 | Supported | |Ethernet PHY| IP101GR | Supported | diff --git a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c index 64a219379b..d7e657d852 100644 --- a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c @@ -131,13 +131,3 @@ exit_mnt_init_spiflash0: #endif INIT_ENV_EXPORT(mnt_init_spiflash0); #endif - -#if defined(PKG_USING_FAL) -int mnt_init_fal(void) -{ - fal_init(); - return 0; -} -INIT_ENV_EXPORT(mnt_init_fal); -#endif - diff --git a/bsp/nuvoton/numaker-iot-m487/board/board.c b/bsp/nuvoton/numaker-iot-m487/board/board.c index 318fe6a0fc..01d68aca61 100644 --- a/bsp/nuvoton/numaker-iot-m487/board/board.c +++ b/bsp/nuvoton/numaker-iot-m487/board/board.c @@ -10,6 +10,7 @@ * ******************************************************************************/ +#include #include #include #include "drv_uart.h" @@ -17,14 +18,6 @@ #include "nutool_pincfg.h" #include "nutool_modclkcfg.h" -#ifdef __CC_ARM - extern int Image$$RW_IRAM1$$ZI$$Limit; -#elif __ICCARM__ - #pragma section="HEAP" -#else - extern int __bss_end; - extern int __ram_top; -#endif /** * This function will initial M487 board. @@ -55,16 +48,8 @@ void rt_hw_board_init(void) /* Lock protected registers */ SYS_LockReg(); - #ifdef RT_USING_HEAP -#ifdef __CC_ARM - rt_system_heap_init((void *)&Image$$RW_IRAM1$$ZI$$Limit, (void *)SRAM_END); -#elif __ICCARM__ - rt_system_heap_init(__segment_end("HEAP"), (void *)SRAM_END); -#else - /* init memory system */ - rt_system_heap_init((void *)&__bss_end, (void *)&__ram_top); -#endif + rt_system_heap_init(HEAP_BEGIN, HEAP_END); #endif /* RT_USING_HEAP */ #if defined(BSP_USING_UART) diff --git a/bsp/nuvoton/numaker-iot-m487/board/board.h b/bsp/nuvoton/numaker-iot-m487/board/board.h index 273621293b..cd45f65e76 100644 --- a/bsp/nuvoton/numaker-iot-m487/board/board.h +++ b/bsp/nuvoton/numaker-iot-m487/board/board.h @@ -1,6 +1,6 @@ /**************************************************************************//** * -* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -17,6 +17,20 @@ #define SRAM_SIZE (160) #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); diff --git a/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_flash.icf b/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_flash.icf index cd694e9ade..0571bfc2e7 100644 --- a/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_flash.icf +++ b/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_flash.icf @@ -5,9 +5,9 @@ define symbol __ICFEDIT_intvec_start__ = 0x00000000; /*-Memory Regions-*/ define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; -define symbol __ICFEDIT_region_ROM_end__ = 0x00080000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0007FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; -define symbol __ICFEDIT_region_RAM_end__ = 0x00028000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20027FFF; /*-Sizes-*/ define symbol __ICFEDIT_size_cstack__ = 0x0400; define symbol __ICFEDIT_size_heap__ = 0x0000; diff --git a/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_link.ld b/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_link.ld index d33fc91ce8..029026af56 100644 --- a/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_link.ld +++ b/bsp/nuvoton/numaker-iot-m487/linking_scripts/m480_link.ld @@ -73,7 +73,7 @@ SECTIONS { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _sidata = .; } > CODE __exidx_end = .; @@ -91,7 +91,7 @@ SECTIONS .data : AT (_sidata) { . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _sdata = . ; *(.data) @@ -99,7 +99,7 @@ SECTIONS *(.gnu.linkonce.d*) . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _edata = . ; } >DATA @@ -107,7 +107,7 @@ SECTIONS .bss : { . = ALIGN(4); - /* This is used by the startup in order to initialize the .bss secion */ + /* This is used by the startup in order to initialize the .bss section */ _sbss = .; *(.bss) @@ -115,7 +115,7 @@ SECTIONS *(COMMON) . = ALIGN(4); - /* This is used by the startup in order to initialize the .bss secion */ + /* This is used by the startup in order to initialize the .bss section */ _ebss = . ; *(.bss.init) diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index bdb0764da6..304aae34a2 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -19,7 +19,7 @@ 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_IDLE_THREAD_STACK_SIZE=1024 # CONFIG_RT_USING_TIMER_SOFT is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y diff --git a/bsp/nuvoton/numaker-pfm-m487/README.md b/bsp/nuvoton/numaker-pfm-m487/README.md index 6f9a6c300c..0e472c1a33 100644 --- a/bsp/nuvoton/numaker-pfm-m487/README.md +++ b/bsp/nuvoton/numaker-pfm-m487/README.md @@ -18,17 +18,17 @@ NuMaker-PFM-M487 provides multiple networking, interfaces, audio recording, play ### 1.2 Interface -| Interface | +| Interface | | -- | | Arduino UNO | -| RJ45 Ethernet | +| RJ45 Ethernet | | USB 1.1/2.0 OTG ports | | A microSD slot | | A 3.5mm Audio connector | ### 1.3 On-board devices -| Device | Descirption | Driver supporting status | +| Device | Description | Driver supporting status | | -- | -- | -- | |SPI flash | W25Q32 | Supported | |Ethernet PHY| IP101GR | Supported | diff --git a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c index 64a219379b..6e7a9ff5de 100644 --- a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c @@ -132,12 +132,3 @@ exit_mnt_init_spiflash0: INIT_ENV_EXPORT(mnt_init_spiflash0); #endif -#if defined(PKG_USING_FAL) -int mnt_init_fal(void) -{ - fal_init(); - return 0; -} -INIT_ENV_EXPORT(mnt_init_fal); -#endif - diff --git a/bsp/nuvoton/numaker-pfm-m487/board/board.c b/bsp/nuvoton/numaker-pfm-m487/board/board.c index 318fe6a0fc..01d68aca61 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/board.c +++ b/bsp/nuvoton/numaker-pfm-m487/board/board.c @@ -10,6 +10,7 @@ * ******************************************************************************/ +#include #include #include #include "drv_uart.h" @@ -17,14 +18,6 @@ #include "nutool_pincfg.h" #include "nutool_modclkcfg.h" -#ifdef __CC_ARM - extern int Image$$RW_IRAM1$$ZI$$Limit; -#elif __ICCARM__ - #pragma section="HEAP" -#else - extern int __bss_end; - extern int __ram_top; -#endif /** * This function will initial M487 board. @@ -55,16 +48,8 @@ void rt_hw_board_init(void) /* Lock protected registers */ SYS_LockReg(); - #ifdef RT_USING_HEAP -#ifdef __CC_ARM - rt_system_heap_init((void *)&Image$$RW_IRAM1$$ZI$$Limit, (void *)SRAM_END); -#elif __ICCARM__ - rt_system_heap_init(__segment_end("HEAP"), (void *)SRAM_END); -#else - /* init memory system */ - rt_system_heap_init((void *)&__bss_end, (void *)&__ram_top); -#endif + rt_system_heap_init(HEAP_BEGIN, HEAP_END); #endif /* RT_USING_HEAP */ #if defined(BSP_USING_UART) diff --git a/bsp/nuvoton/numaker-pfm-m487/board/board.h b/bsp/nuvoton/numaker-pfm-m487/board/board.h index 4f2339210b..cd45f65e76 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/board.h +++ b/bsp/nuvoton/numaker-pfm-m487/board/board.h @@ -17,9 +17,21 @@ #define SRAM_SIZE (160) #define SRAM_END (0x20000000 + SRAM_SIZE * 1024) -#define EE_TYPE AT24C64 +#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__ */ +#endif /* BOARD_H_ */ diff --git a/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_flash.icf b/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_flash.icf index cd694e9ade..0571bfc2e7 100644 --- a/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_flash.icf +++ b/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_flash.icf @@ -5,9 +5,9 @@ define symbol __ICFEDIT_intvec_start__ = 0x00000000; /*-Memory Regions-*/ define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; -define symbol __ICFEDIT_region_ROM_end__ = 0x00080000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0007FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; -define symbol __ICFEDIT_region_RAM_end__ = 0x00028000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20027FFF; /*-Sizes-*/ define symbol __ICFEDIT_size_cstack__ = 0x0400; define symbol __ICFEDIT_size_heap__ = 0x0000; diff --git a/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_link.ld b/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_link.ld index d33fc91ce8..029026af56 100644 --- a/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_link.ld +++ b/bsp/nuvoton/numaker-pfm-m487/linking_scripts/m480_link.ld @@ -73,7 +73,7 @@ SECTIONS { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _sidata = .; } > CODE __exidx_end = .; @@ -91,7 +91,7 @@ SECTIONS .data : AT (_sidata) { . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _sdata = . ; *(.data) @@ -99,7 +99,7 @@ SECTIONS *(.gnu.linkonce.d*) . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _edata = . ; } >DATA @@ -107,7 +107,7 @@ SECTIONS .bss : { . = ALIGN(4); - /* This is used by the startup in order to initialize the .bss secion */ + /* This is used by the startup in order to initialize the .bss section */ _sbss = .; *(.bss) @@ -115,7 +115,7 @@ SECTIONS *(COMMON) . = ALIGN(4); - /* This is used by the startup in order to initialize the .bss secion */ + /* This is used by the startup in order to initialize the .bss section */ _ebss = . ; *(.bss.init) -- GitLab