From 42fdef91a8700a7b128de0e2eaeec59ffd159d73 Mon Sep 17 00:00:00 2001 From: Ouxiaolong <1576690133@qq.com> Date: Sun, 2 Jan 2022 09:14:03 +0800 Subject: [PATCH] [bsp]gd32105r-start, gd32205r-start, gd32305r-start --- bsp/gd32/README.md | 6 + bsp/gd32/docs/GD32系列BSP制作教程.md | 165 +- bsp/gd32/docs/figures/frame.png | Bin 23635 -> 55636 bytes bsp/gd32/docs/figures/scons_mdk5.png | Bin 94546 -> 19725 bytes bsp/gd32/gd32105r-start/.config | 669 +++ bsp/gd32/gd32105r-start/Kconfig | 21 + bsp/gd32/gd32105r-start/README.md | 88 + bsp/gd32/gd32105r-start/SConscript | 15 + bsp/gd32/gd32105r-start/SConstruct | 60 + .../gd32105r-start/applications/SConscript | 11 + bsp/gd32/gd32105r-start/applications/main.c | 35 + bsp/gd32/gd32105r-start/board/Kconfig | 126 + bsp/gd32/gd32105r-start/board/SConscript | 28 + bsp/gd32/gd32105r-start/board/board.c | 85 + bsp/gd32/gd32105r-start/board/board.h | 46 + .../gd32105r-start/board/gd32f10x_libopt.h | 64 + .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 + .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32105r-start/figures/board.jpg | Bin 0 -> 133999 bytes bsp/gd32/gd32105r-start/project.uvoptx | 180 + bsp/gd32/gd32105r-start/project.uvproj | 737 ++++ bsp/gd32/gd32105r-start/project.uvprojx | 769 ++++ bsp/gd32/gd32105r-start/rtconfig.h | 212 + bsp/gd32/gd32105r-start/rtconfig.py | 150 + bsp/gd32/gd32105r-start/template.uvoptx | 180 + bsp/gd32/gd32105r-start/template.uvproj | 628 +++ bsp/gd32/gd32105r-start/template.uvprojx | 418 ++ bsp/gd32/gd32205r-start/.config | 636 +++ bsp/gd32/gd32205r-start/Kconfig | 21 + bsp/gd32/gd32205r-start/README.md | 101 + bsp/gd32/gd32205r-start/SConscript | 15 + bsp/gd32/gd32205r-start/SConstruct | 60 + .../gd32205r-start/applications/SConscript | 11 + bsp/gd32/gd32205r-start/applications/main.c | 35 + bsp/gd32/gd32205r-start/board/Kconfig | 85 + bsp/gd32/gd32205r-start/board/SConscript | 28 + bsp/gd32/gd32205r-start/board/board.c | 85 + bsp/gd32/gd32205r-start/board/board.h | 47 + .../gd32205r-start/board/gd32f20x_libopt.h | 70 + .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 + .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32205r-start/figures/board.jpg | Bin 0 -> 161049 bytes bsp/gd32/gd32205r-start/project.uvoptx | 180 + bsp/gd32/gd32205r-start/project.uvproj | 737 ++++ bsp/gd32/gd32205r-start/project.uvprojx | 726 ++++ bsp/gd32/gd32205r-start/rtconfig.h | 200 + bsp/gd32/gd32205r-start/rtconfig.py | 150 + bsp/gd32/gd32205r-start/template.uvoptx | 180 + bsp/gd32/gd32205r-start/template.uvproj | 628 +++ bsp/gd32/gd32205r-start/template.uvprojx | 417 ++ bsp/gd32/gd32305r-start/.config | 636 +++ bsp/gd32/gd32305r-start/Kconfig | 21 + bsp/gd32/gd32305r-start/README.md | 88 + bsp/gd32/gd32305r-start/SConscript | 15 + bsp/gd32/gd32305r-start/SConstruct | 60 + .../gd32305r-start/applications/SConscript | 11 + bsp/gd32/gd32305r-start/applications/main.c | 35 + bsp/gd32/gd32305r-start/board/Kconfig | 85 + bsp/gd32/gd32305r-start/board/SConscript | 28 + bsp/gd32/gd32305r-start/board/board.c | 85 + bsp/gd32/gd32305r-start/board/board.h | 47 + .../gd32305r-start/board/gd32f30x_libopt.h | 65 + .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 + .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32305r-start/figures/board.jpg | Bin 0 -> 130595 bytes bsp/gd32/gd32305r-start/project.uvoptx | 180 + bsp/gd32/gd32305r-start/project.uvproj | 737 ++++ bsp/gd32/gd32305r-start/project.uvprojx | 727 ++++ bsp/gd32/gd32305r-start/rtconfig.h | 200 + bsp/gd32/gd32305r-start/rtconfig.py | 150 + bsp/gd32/gd32305r-start/template.uvoptx | 180 + bsp/gd32/gd32305r-start/template.uvproj | 628 +++ bsp/gd32/gd32305r-start/template.uvprojx | 418 ++ bsp/gd32/gd32407v-start/.config | 103 +- bsp/gd32/gd32407v-start/README.md | 2 +- bsp/gd32/gd32407v-start/SConstruct | 8 +- bsp/gd32/gd32407v-start/applications/main.c | 2 +- bsp/gd32/gd32407v-start/board/Kconfig | 8 +- bsp/gd32/gd32407v-start/board/SConscript | 8 +- bsp/gd32/gd32407v-start/board/board.c | 2 +- bsp/gd32/gd32407v-start/board/board.h | 2 +- bsp/gd32/gd32407v-start/project.uvoptx | 654 ++- bsp/gd32/gd32407v-start/project.uvproj | 175 +- bsp/gd32/gd32407v-start/project.uvprojx | 397 +- bsp/gd32/gd32407v-start/rtconfig.h | 66 +- bsp/gd32/gd32407v-start/rtconfig.py | 2 +- bsp/gd32/gd32407v-start/template.uvoptx | 14 +- bsp/gd32/gd32407v-start/template.uvproj | 16 +- bsp/gd32/gd32407v-start/template.uvprojx | 21 +- .../CMSIS/GD/GD32F10x/Include/gd32f10x.h | 380 ++ .../GD/GD32F10x/Include/system_gd32f10x.h | 60 + .../GD32F10x/Source/ARM/startup_gd32f10x_cl.s | 390 ++ .../GD32F10x/Source/ARM/startup_gd32f10x_hd.s | 371 ++ .../GD32F10x/Source/ARM/startup_gd32f10x_md.s | 328 ++ .../GD32F10x/Source/ARM/startup_gd32f10x_xd.s | 371 ++ .../GD32F10x/Source/GCC/startup_gd32f10x_cl.s | 273 ++ .../GD32F10x/Source/GCC/startup_gd32f10x_hd.s | 257 ++ .../GD32F10x/Source/GCC/startup_gd32f10x_md.s | 230 ++ .../GD32F10x/Source/GCC/startup_gd32f10x_xd.s | 257 ++ .../GD32F10x/Source/IAR/startup_gd32f10x_cl.s | 528 +++ .../GD32F10x/Source/IAR/startup_gd32f10x_hd.s | 490 +++ .../GD32F10x/Source/IAR/startup_gd32f10x_md.s | 399 ++ .../GD32F10x/Source/IAR/startup_gd32f10x_xd.s | 490 +++ .../GD/GD32F10x/Source/system_gd32f10x.c | 1041 +++++ .../CMSIS/core_cm3.h | 1638 ++++++++ .../CMSIS/core_cmFunc.h | 637 +++ .../CMSIS/core_cmInstr.h | 687 +++ .../Include/gd32f10x_adc.h | 367 ++ .../Include/gd32f10x_bkp.h | 229 + .../Include/gd32f10x_can.h | 754 ++++ .../Include/gd32f10x_crc.h | 80 + .../Include/gd32f10x_dac.h | 249 ++ .../Include/gd32f10x_dbg.h | 152 + .../Include/gd32f10x_dma.h | 289 ++ .../Include/gd32f10x_enet.h | 1497 +++++++ .../Include/gd32f10x_exmc.h | 431 ++ .../Include/gd32f10x_exti.h | 257 ++ .../Include/gd32f10x_fmc.h | 369 ++ .../Include/gd32f10x_fwdgt.h | 107 + .../Include/gd32f10x_gpio.h | 498 +++ .../Include/gd32f10x_i2c.h | 347 ++ .../Include/gd32f10x_misc.h | 94 + .../Include/gd32f10x_pmu.h | 128 + .../Include/gd32f10x_rcu.h | 923 +++++ .../Include/gd32f10x_rtc.h | 151 + .../Include/gd32f10x_sdio.h | 429 ++ .../Include/gd32f10x_spi.h | 327 ++ .../Include/gd32f10x_timer.h | 729 ++++ .../Include/gd32f10x_usart.h | 377 ++ .../Include/gd32f10x_wwdgt.h | 89 + .../Source/gd32f10x_adc.c | 932 +++++ .../Source/gd32f10x_bkp.c | 295 ++ .../Source/gd32f10x_can.c | 1053 +++++ .../Source/gd32f10x_crc.c | 130 + .../Source/gd32f10x_dac.c | 558 +++ .../Source/gd32f10x_dbg.c | 152 + .../Source/gd32f10x_dma.c | 737 ++++ .../Source/gd32f10x_enet.c | 3079 ++++++++++++++ .../Source/gd32f10x_exmc.c | 645 +++ .../Source/gd32f10x_exti.c | 254 ++ .../Source/gd32f10x_fmc.c | 964 +++++ .../Source/gd32f10x_fwdgt.c | 154 + .../Source/gd32f10x_gpio.c | 538 +++ .../Source/gd32f10x_i2c.c | 714 ++++ .../Source/gd32f10x_misc.c | 186 + .../Source/gd32f10x_pmu.c | 282 ++ .../Source/gd32f10x_rcu.c | 1193 ++++++ .../Source/gd32f10x_rtc.c | 276 ++ .../Source/gd32f10x_sdio.c | 813 ++++ .../Source/gd32f10x_spi.c | 717 ++++ .../Source/gd32f10x_timer.c | 2003 +++++++++ .../Source/gd32f10x_usart.c | 766 ++++ .../Source/gd32f10x_wwdgt.c | 149 + .../class/device/audio/Include/audio_core.h | 261 ++ .../device/audio/Include/audio_out_itf.h | 76 + .../class/device/audio/Source/audio_core.c | 549 +++ .../class/device/audio/Source/audio_out_itf.c | 242 ++ .../class/device/cdc/Include/cdc_acm_core.h | 164 + .../class/device/cdc/Source/cdc_acm_core.c | 509 +++ .../class/device/dfu/Include/dfu_core.h | 179 + .../class/device/dfu/Source/dfu_core.c | 675 +++ .../device/hid/Include/custom_hid_core.h | 67 + .../device/hid/Include/standard_hid_core.h | 66 + .../class/device/hid/Include/usb_hid.h | 83 + .../class/device/hid/Source/custom_hid_core.c | 503 +++ .../device/hid/Source/standard_hid_core.c | 427 ++ .../class/device/iap/Include/usb_iap_core.h | 82 + .../class/device/iap/Source/usb_iap_core.c | 596 +++ .../class/device/msc/Include/usbd_msc_bbb.h | 129 + .../class/device/msc/Include/usbd_msc_core.h | 85 + .../class/device/msc/Include/usbd_msc_data.h | 49 + .../class/device/msc/Include/usbd_msc_mem.h | 59 + .../class/device/msc/Include/usbd_msc_scsi.h | 126 + .../class/device/msc/Source/usbd_msc_bbb.c | 283 ++ .../class/device/msc/Source/usbd_msc_core.c | 316 ++ .../class/device/msc/Source/usbd_msc_data.c | 73 + .../class/device/msc/Source/usbd_msc_scsi.c | 728 ++++ .../device/printer/Include/printer_core.h | 73 + .../device/printer/Source/printer_core.c | 310 ++ .../device/Include/usb_ch9_std.h | 211 + .../device/Include/usbd_core.h | 333 ++ .../device/Include/usbd_enum.h | 111 + .../device/Include/usbd_pwr.h | 67 + .../device/Include/usbd_transc.h | 64 + .../device/Source/usbd_core.c | 127 + .../device/Source/usbd_enum.c | 747 ++++ .../device/Source/usbd_pwr.c | 60 + .../device/Source/usbd_transc.c | 208 + .../usbd/Include/usbd_lld_core.h | 73 + .../usbd/Include/usbd_lld_int.h | 48 + .../usbd/Include/usbd_lld_regs.h | 227 + .../usbd/Source/usbd_lld_core.c | 630 +++ .../usbd/Source/usbd_lld_int.c | 276 ++ .../device/class/audio/Include/audio_core.h | 300 ++ .../class/audio/Include/audio_out_itf.h | 76 + .../device/class/audio/Source/audio_core.c | 811 ++++ .../device/class/audio/Source/audio_out_itf.c | 228 + .../device/class/cdc/Include/cdc_acm_core.h | 66 + .../device/class/cdc/Source/cdc_acm_core.c | 524 +++ .../device/class/dfu/Include/dfu_core.h | 176 + .../device/class/dfu/Include/dfu_mal.h | 84 + .../device/class/dfu/Source/dfu_core.c | 653 +++ .../device/class/dfu/Source/dfu_mal.c | 233 ++ .../class/hid/Include/custom_hid_core.h | 69 + .../class/hid/Include/standard_hid_core.h | 68 + .../device/class/hid/Source/custom_hid_core.c | 489 +++ .../class/hid/Source/standard_hid_core.c | 390 ++ .../device/class/iap/Include/usb_iap_core.h | 87 + .../device/class/iap/Source/usb_iap_core.c | 563 +++ .../device/class/msc/Include/usbd_msc_bbb.h | 101 + .../device/class/msc/Include/usbd_msc_core.h | 59 + .../device/class/msc/Include/usbd_msc_data.h | 49 + .../device/class/msc/Include/usbd_msc_mem.h | 59 + .../device/class/msc/Include/usbd_msc_scsi.h | 50 + .../device/class/msc/Source/usbd_msc_bbb.c | 287 ++ .../device/class/msc/Source/usbd_msc_core.c | 319 ++ .../device/class/msc/Source/usbd_msc_data.c | 73 + .../device/class/msc/Source/usbd_msc_scsi.c | 724 ++++ .../class/printer/Include/printer_core.h | 78 + .../class/printer/Source/printer_core.c | 309 ++ .../device/core/Include/usbd_core.h | 103 + .../device/core/Include/usbd_enum.h | 105 + .../device/core/Include/usbd_transc.h | 56 + .../device/core/Source/usbd_core.c | 320 ++ .../device/core/Source/usbd_enum.c | 764 ++++ .../device/core/Source/usbd_transc.c | 265 ++ .../driver/Include/drv_usb_core.h | 163 + .../driver/Include/drv_usb_dev.h | 300 ++ .../driver/Include/drv_usb_host.h | 193 + .../driver/Include/drv_usb_hw.h | 69 + .../driver/Include/drv_usb_regs.h | 662 +++ .../driver/Include/drv_usbd_int.h | 45 + .../driver/Include/drv_usbh_int.h | 56 + .../driver/Source/drv_usb_core.c | 344 ++ .../driver/Source/drv_usb_dev.c | 612 +++ .../driver/Source/drv_usb_host.c | 452 ++ .../driver/Source/drv_usbd_int.c | 497 +++ .../driver/Source/drv_usbh_int.c | 622 +++ .../host/class/hid/Include/usbh_hid_core.h | 212 + .../host/class/hid/Include/usbh_hid_keybd.h | 303 ++ .../host/class/hid/Include/usbh_hid_mouse.h | 59 + .../host/class/hid/Include/usbh_hid_parser.h | 62 + .../host/class/hid/Include/usbh_hid_usage.h | 141 + .../host/class/hid/Source/usbh_hid_core.c | 676 +++ .../host/class/hid/Source/usbh_hid_keybd.c | 399 ++ .../host/class/hid/Source/usbh_hid_mouse.c | 216 + .../host/class/hid/Source/usbh_hid_parser.c | 148 + .../host/class/msc/Include/usbh_msc_bbb.h | 150 + .../host/class/msc/Include/usbh_msc_core.h | 124 + .../host/class/msc/Include/usbh_msc_scsi.h | 100 + .../host/class/msc/Source/usbh_msc_bbb.c | 362 ++ .../host/class/msc/Source/usbh_msc_core.c | 561 +++ .../host/class/msc/Source/usbh_msc_fatfs.c | 233 ++ .../host/class/msc/Source/usbh_msc_scsi.c | 400 ++ .../host/core/Include/usbh_core.h | 274 ++ .../host/core/Include/usbh_enum.h | 71 + .../host/core/Include/usbh_pipe.h | 100 + .../host/core/Include/usbh_transc.h | 51 + .../host/core/Source/usbh_core.c | 650 +++ .../host/core/Source/usbh_enum.c | 693 ++++ .../host/core/Source/usbh_pipe.c | 174 + .../host/core/Source/usbh_transc.c | 371 ++ .../ustd/class/cdc/usb_cdc.h | 180 + .../ustd/class/hid/usb_hid.h | 83 + .../ustd/class/msc/msc_bbb.h | 69 + .../ustd/class/msc/msc_scsi.h | 117 + .../ustd/class/msc/usb_msc.h | 68 + .../ustd/common/usb_ch9_std.h | 248 ++ .../GD32F10x_Firmware_Library/SConscript | 60 + .../CMSIS/GD/GD32F20x/Include/gd32f20x.h | 272 ++ .../GD/GD32F20x/Include/system_gd32f20x.h | 58 + .../GD32F20x/Source/ARM/startup_gd32f20x_cl.s | 436 ++ .../GD32F20x/Source/GCC/startup_gd32f20x_cl.s | 307 ++ .../GD32F20x/Source/IAR/startup_gd32f20x_cl.s | 621 +++ .../GD/GD32F20x/Source/system_gd32f20x.c | 1113 +++++ .../CMSIS/cmsis_armcc.h | 734 ++++ .../CMSIS/core_cm3.h | 1638 ++++++++ .../CMSIS/core_cmFunc.h | 616 +++ .../CMSIS/core_cmInstr.h | 618 +++ .../Include/gd32f20x_adc.h | 411 ++ .../Include/gd32f20x_bkp.h | 273 ++ .../Include/gd32f20x_can.h | 758 ++++ .../Include/gd32f20x_cau.h | 258 ++ .../Include/gd32f20x_crc.h | 80 + .../Include/gd32f20x_dac.h | 247 ++ .../Include/gd32f20x_dbg.h | 146 + .../Include/gd32f20x_dci.h | 236 ++ .../Include/gd32f20x_dma.h | 300 ++ .../Include/gd32f20x_enet.h | 1499 +++++++ .../Include/gd32f20x_exmc.h | 920 +++++ .../Include/gd32f20x_exti.h | 258 ++ .../Include/gd32f20x_fmc.h | 369 ++ .../Include/gd32f20x_fwdgt.h | 109 + .../Include/gd32f20x_gpio.h | 718 ++++ .../Include/gd32f20x_hau.h | 208 + .../Include/gd32f20x_i2c.h | 352 ++ .../Include/gd32f20x_misc.h | 96 + .../Include/gd32f20x_pmu.h | 129 + .../Include/gd32f20x_rcu.h | 1086 +++++ .../Include/gd32f20x_rtc.h | 151 + .../Include/gd32f20x_sdio.h | 433 ++ .../Include/gd32f20x_spi.h | 346 ++ .../Include/gd32f20x_timer.h | 731 ++++ .../Include/gd32f20x_tli.h | 368 ++ .../Include/gd32f20x_trng.h | 105 + .../Include/gd32f20x_usart.h | 449 ++ .../Include/gd32f20x_wwdgt.h | 91 + .../Source/gd32f20x_adc.c | 1019 +++++ .../Source/gd32f20x_bkp.c | 421 ++ .../Source/gd32f20x_can.c | 1035 +++++ .../Source/gd32f20x_cau.c | 388 ++ .../Source/gd32f20x_cau_aes.c | 372 ++ .../Source/gd32f20x_cau_des.c | 191 + .../Source/gd32f20x_cau_tdes.c | 207 + .../Source/gd32f20x_crc.c | 130 + .../Source/gd32f20x_dac.c | 557 +++ .../Source/gd32f20x_dbg.c | 152 + .../Source/gd32f20x_dci.c | 344 ++ .../Source/gd32f20x_dma.c | 658 +++ .../Source/gd32f20x_enet.c | 3079 ++++++++++++++ .../Source/gd32f20x_exmc.c | 1178 ++++++ .../Source/gd32f20x_exti.c | 255 ++ .../Source/gd32f20x_fmc.c | 966 +++++ .../Source/gd32f20x_fwdgt.c | 158 + .../Source/gd32f20x_gpio.c | 726 ++++ .../Source/gd32f20x_hau.c | 331 ++ .../Source/gd32f20x_hau_sha_md5.c | 422 ++ .../Source/gd32f20x_i2c.c | 720 ++++ .../Source/gd32f20x_misc.c | 186 + .../Source/gd32f20x_pmu.c | 281 ++ .../Source/gd32f20x_rcu.c | 1336 ++++++ .../Source/gd32f20x_rtc.c | 276 ++ .../Source/gd32f20x_sdio.c | 817 ++++ .../Source/gd32f20x_spi.c | 782 ++++ .../Source/gd32f20x_timer.c | 2000 +++++++++ .../Source/gd32f20x_tli.c | 481 +++ .../Source/gd32f20x_trng.c | 156 + .../Source/gd32f20x_usart.c | 923 +++++ .../Source/gd32f20x_wwdgt.c | 149 + .../device/class/audio/Include/audio_core.h | 300 ++ .../class/audio/Include/audio_out_itf.h | 76 + .../device/class/audio/Source/audio_core.c | 787 ++++ .../device/class/audio/Source/audio_out_itf.c | 228 + .../device/class/cdc/Include/cdc_acm_core.h | 66 + .../device/class/cdc/Source/cdc_acm_core.c | 525 +++ .../device/class/dfu/Include/dfu_core.h | 176 + .../device/class/dfu/Include/dfu_mal.h | 84 + .../device/class/dfu/Source/dfu_core.c | 653 +++ .../device/class/dfu/Source/dfu_mal.c | 233 ++ .../class/hid/Include/custom_hid_core.h | 69 + .../class/hid/Include/standard_hid_core.h | 68 + .../device/class/hid/Source/custom_hid_core.c | 490 +++ .../class/hid/Source/standard_hid_core.c | 390 ++ .../device/class/iap/Include/usb_iap_core.h | 87 + .../device/class/iap/Source/usb_iap_core.c | 571 +++ .../device/class/msc/Include/usbd_msc_bbb.h | 101 + .../device/class/msc/Include/usbd_msc_core.h | 59 + .../device/class/msc/Include/usbd_msc_data.h | 49 + .../device/class/msc/Include/usbd_msc_mem.h | 59 + .../device/class/msc/Include/usbd_msc_scsi.h | 50 + .../device/class/msc/Source/usbd_msc_bbb.c | 287 ++ .../device/class/msc/Source/usbd_msc_core.c | 319 ++ .../device/class/msc/Source/usbd_msc_data.c | 73 + .../device/class/msc/Source/usbd_msc_scsi.c | 725 ++++ .../class/printer/Include/printer_core.h | 78 + .../class/printer/Source/printer_core.c | 310 ++ .../device/core/Include/usbd_core.h | 103 + .../device/core/Include/usbd_enum.h | 105 + .../device/core/Include/usbd_transc.h | 56 + .../device/core/Source/usbd_core.c | 320 ++ .../device/core/Source/usbd_enum.c | 764 ++++ .../device/core/Source/usbd_transc.c | 265 ++ .../driver/Include/drv_usb_core.h | 163 + .../driver/Include/drv_usb_dev.h | 299 ++ .../driver/Include/drv_usb_host.h | 193 + .../driver/Include/drv_usb_hw.h | 64 + .../driver/Include/drv_usb_regs.h | 661 +++ .../driver/Include/drv_usbd_int.h | 45 + .../driver/Include/drv_usbh_int.h | 56 + .../driver/Source/drv_usb_core.c | 344 ++ .../driver/Source/drv_usb_dev.c | 612 +++ .../driver/Source/drv_usb_host.c | 452 ++ .../driver/Source/drv_usbd_int.c | 510 +++ .../driver/Source/drv_usbh_int.c | 622 +++ .../host/class/hid/Include/usbh_hid_core.h | 212 + .../host/class/hid/Include/usbh_hid_keybd.h | 303 ++ .../host/class/hid/Include/usbh_hid_mouse.h | 59 + .../host/class/hid/Include/usbh_hid_parser.h | 62 + .../host/class/hid/Include/usbh_hid_usage.h | 141 + .../host/class/hid/Source/usbh_hid_core.c | 676 +++ .../host/class/hid/Source/usbh_hid_keybd.c | 399 ++ .../host/class/hid/Source/usbh_hid_mouse.c | 216 + .../host/class/hid/Source/usbh_hid_parser.c | 148 + .../host/class/msc/Include/usbh_msc_bbb.h | 150 + .../host/class/msc/Include/usbh_msc_core.h | 124 + .../host/class/msc/Include/usbh_msc_scsi.h | 100 + .../host/class/msc/Source/usbh_msc_bbb.c | 362 ++ .../host/class/msc/Source/usbh_msc_core.c | 556 +++ .../host/class/msc/Source/usbh_msc_fatfs.c | 233 ++ .../host/class/msc/Source/usbh_msc_scsi.c | 400 ++ .../host/core/Include/usbh_core.h | 274 ++ .../host/core/Include/usbh_enum.h | 71 + .../host/core/Include/usbh_pipe.h | 100 + .../host/core/Include/usbh_transc.h | 51 + .../host/core/Source/usbh_core.c | 650 +++ .../host/core/Source/usbh_enum.c | 693 ++++ .../host/core/Source/usbh_pipe.c | 174 + .../host/core/Source/usbh_transc.c | 371 ++ .../ustd/class/cdc/usb_cdc.h | 180 + .../ustd/class/hid/usb_hid.h | 83 + .../ustd/class/msc/msc_bbb.h | 69 + .../ustd/class/msc/msc_scsi.h | 117 + .../ustd/class/msc/usb_msc.h | 68 + .../ustd/common/usb_ch9_std.h | 248 ++ .../GD32F20x_Firmware_Library/SConscript | 57 + .../CMSIS/GD/GD32F30x/Include/gd32f30x.h | 356 ++ .../GD/GD32F30x/Include/system_gd32f30x.h | 57 + .../GD32F30x/Source/ARM/startup_gd32f30x_cl.s | 385 ++ .../GD32F30x/Source/ARM/startup_gd32f30x_hd.s | 365 ++ .../GD32F30x/Source/ARM/startup_gd32f30x_xd.s | 365 ++ .../GD32F30x/Source/GCC/startup_gd32f30x_cl.s | 271 ++ .../GD32F30x/Source/GCC/startup_gd32f30x_hd.s | 257 ++ .../GD32F30x/Source/GCC/startup_gd32f30x_xd.s | 257 ++ .../GD32F30x/Source/IAR/startup_gd32f30x_cl.s | 525 +++ .../GD32F30x/Source/IAR/startup_gd32f30x_hd.s | 487 +++ .../GD32F30x/Source/IAR/startup_gd32f30x_xd.s | 487 +++ .../GD/GD32F30x/Source/system_gd32f30x.c | 996 +++++ .../CMSIS/core_cm4.h | 0 .../CMSIS/core_cm4_simd.h | 0 .../CMSIS/core_cmFunc.h | 616 +++ .../CMSIS/core_cmInstr.h | 618 +++ .../Include/gd32f30x_adc.h | 403 ++ .../Include/gd32f30x_bkp.h | 244 ++ .../Include/gd32f30x_can.h | 754 ++++ .../Include/gd32f30x_crc.h | 81 + .../Include/gd32f30x_ctc.h | 186 + .../Include/gd32f30x_dac.h | 250 ++ .../Include/gd32f30x_dbg.h | 158 + .../Include/gd32f30x_dma.h | 285 ++ .../Include/gd32f30x_enet.h | 1702 ++++++++ .../Include/gd32f30x_exmc.h | 446 ++ .../Include/gd32f30x_exti.h | 255 ++ .../Include/gd32f30x_fmc.h | 375 ++ .../Include/gd32f30x_fwdgt.h | 107 + .../Include/gd32f30x_gpio.h | 536 +++ .../Include/gd32f30x_i2c.h | 355 ++ .../Include/gd32f30x_misc.h | 94 + .../Include/gd32f30x_pmu.h | 187 + .../Include/gd32f30x_rcu.h | 1053 +++++ .../Include/gd32f30x_rtc.h | 138 + .../Include/gd32f30x_sdio.h | 434 ++ .../Include/gd32f30x_spi.h | 365 ++ .../Include/gd32f30x_timer.h | 752 ++++ .../Include/gd32f30x_usart.h | 444 ++ .../Include/gd32f30x_wwdgt.h | 90 + .../Source/gd32f30x_adc.c | 941 +++++ .../Source/gd32f30x_bkp.c | 328 ++ .../Source/gd32f30x_can.c | 1042 +++++ .../Source/gd32f30x_crc.c | 130 + .../Source/gd32f30x_ctc.c | 393 ++ .../Source/gd32f30x_dac.c | 541 +++ .../Source/gd32f30x_dbg.c | 164 + .../Source/gd32f30x_dma.c | 735 ++++ .../Source/gd32f30x_enet.c | 3680 +++++++++++++++++ .../Source/gd32f30x_exmc.c | 677 +++ .../Source/gd32f30x_exti.c | 253 ++ .../Source/gd32f30x_fmc.c | 1009 +++++ .../Source/gd32f30x_fwdgt.c | 158 + .../Source/gd32f30x_gpio.c | 583 +++ .../Source/gd32f30x_i2c.c | 737 ++++ .../Source/gd32f30x_misc.c | 175 + .../Source/gd32f30x_pmu.c | 386 ++ .../Source/gd32f30x_rcu.c | 1326 ++++++ .../Source/gd32f30x_rtc.c | 230 ++ .../Source/gd32f30x_sdio.c | 809 ++++ .../Source/gd32f30x_spi.c | 859 ++++ .../Source/gd32f30x_timer.c | 2042 +++++++++ .../Source/gd32f30x_usart.c | 909 ++++ .../Source/gd32f30x_wwdgt.c | 149 + .../class/device/audio/Include/audio_core.h | 260 ++ .../device/audio/Include/audio_out_itf.h | 76 + .../class/device/audio/Source/audio_core.c | 549 +++ .../class/device/audio/Source/audio_out_itf.c | 242 ++ .../class/device/cdc/Include/cdc_acm_core.h | 163 + .../class/device/cdc/Source/cdc_acm_core.c | 510 +++ .../class/device/dfu/Include/dfu_core.h | 179 + .../class/device/dfu/Source/dfu_core.c | 674 +++ .../device/hid/Include/custom_hid_core.h | 67 + .../device/hid/Include/standard_hid_core.h | 66 + .../device/hid/Include/std_hid_mouse_core.h | 69 + .../class/device/hid/Include/usb_hid.h | 83 + .../class/device/hid/Source/custom_hid_core.c | 503 +++ .../device/hid/Source/standard_hid_core.c | 427 ++ .../device/hid/Source/std_hid_mouse_core.c | 425 ++ .../class/device/iap/Include/usb_iap_core.h | 82 + .../class/device/iap/Source/usb_iap_core.c | 594 +++ .../class/device/msc/Include/usbd_msc_bbb.h | 130 + .../class/device/msc/Include/usbd_msc_core.h | 86 + .../class/device/msc/Include/usbd_msc_data.h | 50 + .../class/device/msc/Include/usbd_msc_mem.h | 60 + .../class/device/msc/Include/usbd_msc_scsi.h | 127 + .../class/device/msc/Source/usbd_msc_bbb.c | 284 ++ .../class/device/msc/Source/usbd_msc_core.c | 316 ++ .../class/device/msc/Source/usbd_msc_data.c | 74 + .../class/device/msc/Source/usbd_msc_scsi.c | 729 ++++ .../device/printer/Include/printer_core.h | 73 + .../device/printer/Source/printer_core.c | 310 ++ .../device/Include/usb_ch9_std.h | 212 + .../device/Include/usbd_core.h | 332 ++ .../device/Include/usbd_enum.h | 111 + .../device/Include/usbd_pwr.h | 67 + .../device/Include/usbd_transc.h | 63 + .../device/Source/usbd_core.c | 129 + .../device/Source/usbd_enum.c | 743 ++++ .../device/Source/usbd_pwr.c | 60 + .../device/Source/usbd_transc.c | 207 + .../usbd/Include/usbd_lld_core.h | 73 + .../usbd/Include/usbd_lld_int.h | 48 + .../usbd/Include/usbd_lld_regs.h | 227 + .../usbd/Source/usbd_lld_core.c | 641 +++ .../usbd/Source/usbd_lld_int.c | 276 ++ .../device/class/audio/Include/audio_core.h | 300 ++ .../class/audio/Include/audio_out_itf.h | 76 + .../device/class/audio/Source/audio_core.c | 809 ++++ .../device/class/audio/Source/audio_out_itf.c | 229 + .../device/class/cdc/Include/cdc_acm_core.h | 66 + .../device/class/cdc/Source/cdc_acm_core.c | 524 +++ .../device/class/dfu/Include/dfu_core.h | 176 + .../device/class/dfu/Include/dfu_mal.h | 84 + .../device/class/dfu/Source/dfu_core.c | 652 +++ .../device/class/dfu/Source/dfu_mal.c | 233 ++ .../class/hid/Include/custom_hid_core.h | 69 + .../class/hid/Include/standard_hid_core.h | 68 + .../device/class/hid/Source/custom_hid_core.c | 488 +++ .../class/hid/Source/standard_hid_core.c | 389 ++ .../device/class/iap/Include/usb_iap_core.h | 87 + .../device/class/iap/Source/usb_iap_core.c | 562 +++ .../device/class/msc/Include/usbd_msc_bbb.h | 101 + .../device/class/msc/Include/usbd_msc_core.h | 59 + .../device/class/msc/Include/usbd_msc_data.h | 49 + .../device/class/msc/Include/usbd_msc_mem.h | 59 + .../device/class/msc/Include/usbd_msc_scsi.h | 50 + .../device/class/msc/Source/usbd_msc_bbb.c | 287 ++ .../device/class/msc/Source/usbd_msc_core.c | 319 ++ .../device/class/msc/Source/usbd_msc_data.c | 73 + .../device/class/msc/Source/usbd_msc_scsi.c | 724 ++++ .../class/printer/Include/printer_core.h | 78 + .../class/printer/Source/printer_core.c | 309 ++ .../device/core/Include/usbd_core.h | 103 + .../device/core/Include/usbd_enum.h | 105 + .../device/core/Include/usbd_transc.h | 56 + .../device/core/Source/usbd_core.c | 320 ++ .../device/core/Source/usbd_enum.c | 764 ++++ .../device/core/Source/usbd_transc.c | 264 ++ .../driver/Include/drv_usb_core.h | 163 + .../driver/Include/drv_usb_dev.h | 300 ++ .../driver/Include/drv_usb_host.h | 193 + .../driver/Include/drv_usb_hw.h | 69 + .../driver/Include/drv_usb_regs.h | 657 +++ .../driver/Include/drv_usbd_int.h | 45 + .../driver/Include/drv_usbh_int.h | 56 + .../driver/Source/drv_usb_core.c | 343 ++ .../driver/Source/drv_usb_dev.c | 610 +++ .../driver/Source/drv_usb_host.c | 452 ++ .../driver/Source/drv_usbd_int.c | 491 +++ .../driver/Source/drv_usbh_int.c | 622 +++ .../host/class/hid/Include/usbh_hid_core.h | 212 + .../host/class/hid/Include/usbh_hid_keybd.h | 303 ++ .../host/class/hid/Include/usbh_hid_mouse.h | 59 + .../host/class/hid/Include/usbh_hid_parser.h | 61 + .../host/class/hid/Include/usbh_hid_usage.h | 141 + .../host/class/hid/Source/usbh_hid_core.c | 675 +++ .../host/class/hid/Source/usbh_hid_keybd.c | 399 ++ .../host/class/hid/Source/usbh_hid_mouse.c | 216 + .../host/class/hid/Source/usbh_hid_parser.c | 148 + .../host/class/msc/Include/usbh_msc_bbb.h | 150 + .../host/class/msc/Include/usbh_msc_core.h | 124 + .../host/class/msc/Include/usbh_msc_scsi.h | 100 + .../host/class/msc/Source/usbh_msc_bbb.c | 362 ++ .../host/class/msc/Source/usbh_msc_core.c | 561 +++ .../host/class/msc/Source/usbh_msc_fatfs.c | 233 ++ .../host/class/msc/Source/usbh_msc_scsi.c | 397 ++ .../host/core/Include/usbh_core.h | 274 ++ .../host/core/Include/usbh_enum.h | 71 + .../host/core/Include/usbh_pipe.h | 100 + .../host/core/Include/usbh_transc.h | 51 + .../host/core/Source/usbh_core.c | 650 +++ .../host/core/Source/usbh_enum.c | 693 ++++ .../host/core/Source/usbh_pipe.c | 174 + .../host/core/Source/usbh_transc.c | 370 ++ .../ustd/class/cdc/usb_cdc.h | 180 + .../ustd/class/hid/usb_hid.h | 83 + .../ustd/class/msc/msc_bbb.h | 69 + .../ustd/class/msc/msc_scsi.h | 117 + .../ustd/class/msc/usb_msc.h | 68 + .../ustd/common/usb_ch9_std.h | 248 ++ .../GD32F30x_Firmware_Library/SConscript | 57 + .../CMSIS/GD/GD32F4xx/Include/gd32f4xx.h | 0 .../GD/GD32F4xx/Include/system_gd32f4xx.h | 0 .../GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s | 0 .../GD32F4xx/Source/GCC/startup_gd32f4xx.s} | 0 .../GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s | 0 .../GD/GD32F4xx/Source/system_gd32f4xx.c | 0 .../CMSIS/core_cm4.h | 1790 ++++++++ .../CMSIS/core_cm4_simd.h | 697 ++++ .../CMSIS/core_cmFunc.h | 0 .../CMSIS/core_cmInstr.h | 0 .../Include/gd32f4xx_adc.h | 0 .../Include/gd32f4xx_can.h | 0 .../Include/gd32f4xx_crc.h | 0 .../Include/gd32f4xx_ctc.h | 0 .../Include/gd32f4xx_dac.h | 0 .../Include/gd32f4xx_dbg.h | 0 .../Include/gd32f4xx_dci.h | 0 .../Include/gd32f4xx_dma.h | 0 .../Include/gd32f4xx_enet.h | 0 .../Include/gd32f4xx_exmc.h | 0 .../Include/gd32f4xx_exti.h | 0 .../Include/gd32f4xx_fmc.h | 0 .../Include/gd32f4xx_fwdgt.h | 0 .../Include/gd32f4xx_gpio.h | 0 .../Include/gd32f4xx_i2c.h | 0 .../Include/gd32f4xx_ipa.h | 0 .../Include/gd32f4xx_iref.h | 0 .../Include/gd32f4xx_misc.h | 0 .../Include/gd32f4xx_pmu.h | 0 .../Include/gd32f4xx_rcu.h | 0 .../Include/gd32f4xx_rtc.h | 0 .../Include/gd32f4xx_sdio.h | 0 .../Include/gd32f4xx_spi.h | 0 .../Include/gd32f4xx_syscfg.h | 0 .../Include/gd32f4xx_timer.h | 0 .../Include/gd32f4xx_tli.h | 0 .../Include/gd32f4xx_trng.h | 0 .../Include/gd32f4xx_usart.h | 0 .../Include/gd32f4xx_wwdgt.h | 0 .../Source/gd32f4xx_adc.c | 0 .../Source/gd32f4xx_can.c | 0 .../Source/gd32f4xx_crc.c | 0 .../Source/gd32f4xx_ctc.c | 0 .../Source/gd32f4xx_dac.c | 0 .../Source/gd32f4xx_dbg.c | 0 .../Source/gd32f4xx_dci.c | 0 .../Source/gd32f4xx_dma.c | 0 .../Source/gd32f4xx_enet.c | 0 .../Source/gd32f4xx_exmc.c | 0 .../Source/gd32f4xx_exti.c | 0 .../Source/gd32f4xx_fmc.c | 0 .../Source/gd32f4xx_fwdgt.c | 0 .../Source/gd32f4xx_gpio.c | 0 .../Source/gd32f4xx_i2c.c | 0 .../Source/gd32f4xx_ipa.c | 0 .../Source/gd32f4xx_iref.c | 0 .../Source/gd32f4xx_misc.c | 0 .../Source/gd32f4xx_pmu.c | 0 .../Source/gd32f4xx_rcu.c | 0 .../Source/gd32f4xx_rtc.c | 0 .../Source/gd32f4xx_sdio.c | 0 .../Source/gd32f4xx_spi.c | 0 .../Source/gd32f4xx_syscfg.c | 0 .../Source/gd32f4xx_timer.c | 0 .../Source/gd32f4xx_tli.c | 0 .../Source/gd32f4xx_trng.c | 0 .../Source/gd32f4xx_usart.c | 0 .../Source/gd32f4xx_wwdgt.c | 0 .../device/class/audio/Include/audio_core.h | 300 ++ .../class/audio/Include/audio_out_itf.h | 76 + .../device/class/audio/Source/audio_core.c | 777 ++++ .../device/class/audio/Source/audio_out_itf.c | 228 + .../device/class/cdc/Include/cdc_acm_core.h | 66 + .../device/class/cdc/Source/cdc_acm_core.c | 515 +++ .../device/class/dfu/Include/dfu_core.h | 176 + .../device/class/dfu/Include/dfu_mal.h | 84 + .../device/class/dfu/Source/dfu_core.c | 653 +++ .../device/class/dfu/Source/dfu_mal.c | 233 ++ .../class/hid/Include/custom_hid_core.h | 69 + .../class/hid/Include/standard_hid_core.h | 68 + .../device/class/hid/Source/custom_hid_core.c | 486 +++ .../class/hid/Source/standard_hid_core.c | 384 ++ .../device/class/iap/Include/usb_iap_core.h | 93 + .../device/class/iap/Source/usb_iap_core.c | 571 +++ .../device/class/msc/Include/usbd_msc_bbb.h | 101 + .../device/class/msc/Include/usbd_msc_core.h | 59 + .../device/class/msc/Include/usbd_msc_data.h | 49 + .../device/class/msc/Include/usbd_msc_mem.h | 59 + .../device/class/msc/Include/usbd_msc_scsi.h | 50 + .../device/class/msc/Source/usbd_msc_bbb.c | 287 ++ .../device/class/msc/Source/usbd_msc_core.c | 322 ++ .../device/class/msc/Source/usbd_msc_data.c | 73 + .../device/class/msc/Source/usbd_msc_scsi.c | 685 +++ .../class/printer/Include/printer_core.h | 78 + .../class/printer/Source/printer_core.c | 310 ++ .../device/core/Include/usbd_core.h | 103 + .../device/core/Include/usbd_enum.h | 105 + .../device/core/Include/usbd_transc.h | 56 + .../device/core/Source/usbd_core.c | 320 ++ .../device/core/Source/usbd_enum.c | 764 ++++ .../device/core/Source/usbd_transc.c | 264 ++ .../driver/Include/drv_usb_core.h | 343 ++ .../driver/Include/drv_usb_dev.h | 197 + .../driver/Include/drv_usb_host.h | 123 + .../driver/Include/drv_usb_hw.h | 71 + .../driver/Include/drv_usb_regs.h | 662 +++ .../driver/Include/drv_usbd_int.h | 52 + .../driver/Include/drv_usbh_int.h | 56 + .../driver/Source/drv_usb_core.c | 363 ++ .../driver/Source/drv_usb_dev.c | 664 +++ .../driver/Source/drv_usb_host.c | 476 +++ .../driver/Source/drv_usbd_int.c | 587 +++ .../driver/Source/drv_usbh_int.c | 622 +++ .../host/class/hid/Include/usbh_hid_core.h | 212 + .../host/class/hid/Include/usbh_hid_keybd.h | 303 ++ .../host/class/hid/Include/usbh_hid_mouse.h | 59 + .../host/class/hid/Include/usbh_hid_parser.h | 61 + .../host/class/hid/Include/usbh_hid_usage.h | 141 + .../host/class/hid/Source/usbh_hid_core.c | 675 +++ .../host/class/hid/Source/usbh_hid_keybd.c | 399 ++ .../host/class/hid/Source/usbh_hid_mouse.c | 216 + .../host/class/hid/Source/usbh_hid_parser.c | 148 + .../host/class/msc/Include/usbh_msc_bbb.h | 150 + .../host/class/msc/Include/usbh_msc_core.h | 124 + .../host/class/msc/Include/usbh_msc_scsi.h | 100 + .../host/class/msc/Source/usbh_msc_bbb.c | 362 ++ .../host/class/msc/Source/usbh_msc_core.c | 556 +++ .../host/class/msc/Source/usbh_msc_fatfs.c | 233 ++ .../host/class/msc/Source/usbh_msc_scsi.c | 400 ++ .../host/core/Include/usbh_core.h | 282 ++ .../host/core/Include/usbh_enum.h | 71 + .../host/core/Include/usbh_pipe.h | 100 + .../host/core/Include/usbh_transc.h | 51 + .../host/core/Source/usbh_core.c | 653 +++ .../host/core/Source/usbh_enum.c | 693 ++++ .../host/core/Source/usbh_pipe.c | 174 + .../host/core/Source/usbh_transc.c | 370 ++ .../ustd/class/cdc/usb_cdc.h | 180 + .../ustd/class/hid/usb_hid.h | 83 + .../ustd/class/msc/msc_bbb.h | 69 + .../ustd/class/msc/msc_scsi.h | 117 + .../ustd/class/msc/usb_msc.h | 68 + .../ustd/common/usb_ch9_std.h | 248 ++ .../SConscript | 0 bsp/gd32/libraries/HAL_Drivers/SConscript | 22 - bsp/gd32/libraries/HAL_Drivers/drv_usart.h | 22 - .../{HAL_Drivers => gd32_drivers}/Kconfig | 0 bsp/gd32/libraries/gd32_drivers/SConscript | 36 + .../{HAL_Drivers => gd32_drivers}/drv_gpio.c | 134 +- .../{HAL_Drivers => gd32_drivers}/drv_gpio.h | 31 +- .../libraries/gd32_drivers/drv_soft_i2c.c | 201 + .../libraries/gd32_drivers/drv_soft_i2c.h | 78 + bsp/gd32/libraries/gd32_drivers/drv_spi.c | 356 ++ bsp/gd32/libraries/gd32_drivers/drv_spi.h | 46 + .../libraries/gd32_drivers/drv_spi_flash.c | 87 + .../{HAL_Drivers => gd32_drivers}/drv_usart.c | 151 +- bsp/gd32/libraries/gd32_drivers/drv_usart.h | 54 + bsp/gd32/tools/sdk_dist.py | 17 +- 758 files changed, 225042 insertions(+), 718 deletions(-) create mode 100644 bsp/gd32/gd32105r-start/.config create mode 100644 bsp/gd32/gd32105r-start/Kconfig create mode 100644 bsp/gd32/gd32105r-start/README.md create mode 100644 bsp/gd32/gd32105r-start/SConscript create mode 100644 bsp/gd32/gd32105r-start/SConstruct create mode 100644 bsp/gd32/gd32105r-start/applications/SConscript create mode 100644 bsp/gd32/gd32105r-start/applications/main.c create mode 100644 bsp/gd32/gd32105r-start/board/Kconfig create mode 100644 bsp/gd32/gd32105r-start/board/SConscript create mode 100644 bsp/gd32/gd32105r-start/board/board.c create mode 100644 bsp/gd32/gd32105r-start/board/board.h create mode 100644 bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h create mode 100644 bsp/gd32/gd32105r-start/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32105r-start/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32105r-start/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32105r-start/figures/board.jpg create mode 100644 bsp/gd32/gd32105r-start/project.uvoptx create mode 100644 bsp/gd32/gd32105r-start/project.uvproj create mode 100644 bsp/gd32/gd32105r-start/project.uvprojx create mode 100644 bsp/gd32/gd32105r-start/rtconfig.h create mode 100644 bsp/gd32/gd32105r-start/rtconfig.py create mode 100644 bsp/gd32/gd32105r-start/template.uvoptx create mode 100644 bsp/gd32/gd32105r-start/template.uvproj create mode 100644 bsp/gd32/gd32105r-start/template.uvprojx create mode 100644 bsp/gd32/gd32205r-start/.config create mode 100644 bsp/gd32/gd32205r-start/Kconfig create mode 100644 bsp/gd32/gd32205r-start/README.md create mode 100644 bsp/gd32/gd32205r-start/SConscript create mode 100644 bsp/gd32/gd32205r-start/SConstruct create mode 100644 bsp/gd32/gd32205r-start/applications/SConscript create mode 100644 bsp/gd32/gd32205r-start/applications/main.c create mode 100644 bsp/gd32/gd32205r-start/board/Kconfig create mode 100644 bsp/gd32/gd32205r-start/board/SConscript create mode 100644 bsp/gd32/gd32205r-start/board/board.c create mode 100644 bsp/gd32/gd32205r-start/board/board.h create mode 100644 bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h create mode 100644 bsp/gd32/gd32205r-start/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32205r-start/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32205r-start/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32205r-start/figures/board.jpg create mode 100644 bsp/gd32/gd32205r-start/project.uvoptx create mode 100644 bsp/gd32/gd32205r-start/project.uvproj create mode 100644 bsp/gd32/gd32205r-start/project.uvprojx create mode 100644 bsp/gd32/gd32205r-start/rtconfig.h create mode 100644 bsp/gd32/gd32205r-start/rtconfig.py create mode 100644 bsp/gd32/gd32205r-start/template.uvoptx create mode 100644 bsp/gd32/gd32205r-start/template.uvproj create mode 100644 bsp/gd32/gd32205r-start/template.uvprojx create mode 100644 bsp/gd32/gd32305r-start/.config create mode 100644 bsp/gd32/gd32305r-start/Kconfig create mode 100644 bsp/gd32/gd32305r-start/README.md create mode 100644 bsp/gd32/gd32305r-start/SConscript create mode 100644 bsp/gd32/gd32305r-start/SConstruct create mode 100644 bsp/gd32/gd32305r-start/applications/SConscript create mode 100644 bsp/gd32/gd32305r-start/applications/main.c create mode 100644 bsp/gd32/gd32305r-start/board/Kconfig create mode 100644 bsp/gd32/gd32305r-start/board/SConscript create mode 100644 bsp/gd32/gd32305r-start/board/board.c create mode 100644 bsp/gd32/gd32305r-start/board/board.h create mode 100644 bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h create mode 100644 bsp/gd32/gd32305r-start/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32305r-start/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32305r-start/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32305r-start/figures/board.jpg create mode 100644 bsp/gd32/gd32305r-start/project.uvoptx create mode 100644 bsp/gd32/gd32305r-start/project.uvproj create mode 100644 bsp/gd32/gd32305r-start/project.uvprojx create mode 100644 bsp/gd32/gd32305r-start/rtconfig.h create mode 100644 bsp/gd32/gd32305r-start/rtconfig.py create mode 100644 bsp/gd32/gd32305r-start/template.uvoptx create mode 100644 bsp/gd32/gd32305r-start/template.uvproj create mode 100644 bsp/gd32/gd32305r-start/template.uvprojx create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h create mode 100644 bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h create mode 100644 bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F30x_Firmware_Library}/CMSIS/core_cm4.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F30x_Firmware_Library}/CMSIS/core_cm4_simd.h (100%) create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_wwdgt.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h create mode 100644 bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S => GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s} (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c (100%) create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/core_cmFunc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/CMSIS/core_cmInstr.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c (100%) rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c (100%) create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h create mode 100644 bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h rename bsp/gd32/libraries/{GD32F4xx_HAL => GD32F4xx_Firmware_Library}/SConscript (100%) delete mode 100644 bsp/gd32/libraries/HAL_Drivers/SConscript delete mode 100644 bsp/gd32/libraries/HAL_Drivers/drv_usart.h rename bsp/gd32/libraries/{HAL_Drivers => gd32_drivers}/Kconfig (100%) create mode 100644 bsp/gd32/libraries/gd32_drivers/SConscript rename bsp/gd32/libraries/{HAL_Drivers => gd32_drivers}/drv_gpio.c (81%) rename bsp/gd32/libraries/{HAL_Drivers => gd32_drivers}/drv_gpio.h (54%) create mode 100644 bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c create mode 100644 bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h create mode 100644 bsp/gd32/libraries/gd32_drivers/drv_spi.c create mode 100644 bsp/gd32/libraries/gd32_drivers/drv_spi.h create mode 100644 bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c rename bsp/gd32/libraries/{HAL_Drivers => gd32_drivers}/drv_usart.c (77%) create mode 100644 bsp/gd32/libraries/gd32_drivers/drv_usart.h diff --git a/bsp/gd32/README.md b/bsp/gd32/README.md index 8d7a969ed9..fb706c2723 100644 --- a/bsp/gd32/README.md +++ b/bsp/gd32/README.md @@ -5,6 +5,12 @@ GD32 系列 BSP 目前支持情况如下表所示: | **BSP 文件夹名称** | **开发板名称** | |:------------------------- |:-------------------------- | +| **F1 系列** | | +| [gd32105r-start](gd32105r-start) | 兆易创新 官方 GD32105r-START 开发板 | +| **F2 系列** | | +| [gd32205r-start](gd32205r-start) | 兆易创新 官方 GD32205r-START 开发板 | +| **F3 系列** | | +| [gd32305r-start](gd32305r-start) | 兆易创新 官方 GD32305r-START 开发板 | | **F4 系列** | | | [gd32407v-start](gd32407v-start) | 兆易创新 官方 GD32407V-START 开发板 | diff --git a/bsp/gd32/docs/GD32系列BSP制作教程.md b/bsp/gd32/docs/GD32系列BSP制作教程.md index 6a894cc54a..6f0a4427f7 100644 --- a/bsp/gd32/docs/GD32系列BSP制作教程.md +++ b/bsp/gd32/docs/GD32系列BSP制作教程.md @@ -1,37 +1,32 @@ # GD32 系列 BSP 制作教程 -## 1. BSP 框架介绍 +## 1. BSP 框架介绍 BSP 框架结构如下图所示: ![BSP 框架图](./figures/frame.png) -GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards,其中libraries包含了GD32的通用库,包括每个系列的HAL以及适配RT-Thread的drivers;tools是生成工程的Python脚本工具;另外就是Boards文件,当然这里的Boards有很多,我这里值列举了GD32407V-START。 - - - +GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards,其中libraries包含了GD32的通用库,包括每个系列的Firmware Library以及适配RT-Thread的drivers;tools是生成工程的Python脚本工具;另外就是Boards文件,当然这里的Boards有很多,我这里值列举了GD32407V-START。 ## 2. 知识准备 制作一个 BSP 的过程就是构建一个新系统的过程,因此想要制作出好用的 BSP,要对 RT-Thread 系统的构建过程有一定了解,需要的知识准备如下所示: - 掌握 GD32 系列 BSP 的使用方法 - + 了解 BSP 的使用方法,可以阅读 [BSP 说明文档](../README.md) 中使用教程表格内的文档。 - 了解 Scons 工程构建方法 - + RT-Thread 使用 Scons 作为系统的构建工具,因此了解 Scons 的常用命令对制作新 BSP 是基本要求。 - 了解设备驱动框架 - + 在 RT-Thread 系统中,应用程序通过设备驱动框架来操作硬件,因此了解设备驱动框架,对添加 BSP 驱动是很重要的。 - 了解 Kconfig 语法 - - RT-Thread 系统通过 menuconfig 的方式进行配置,而 menuconfig 中的选项是由 Kconfig 文件决定的,因此想要对 RT-Thread 系统进行配置,需要对 kconfig 语法有一定了解。 - + RT-Thread 系统通过 menuconfig 的方式进行配置,而 menuconfig 中的选项是由 Kconfig 文件决定的,因此想要对 RT-Thread 系统进行配置,需要对 kconfig 语法有一定了解。 ## 3. BSP移植 @@ -53,28 +48,18 @@ GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards ![Download](./figures/dowmload.png) - - 下载好后双击GigaDevice.GD32F4xx_DFP.2.1.0.pack运行即可: - - ![install paxk](./figures/install_pack.png) - - 点击[Next]即可安装完成。 ![finish](./figures/pack_finish.png) - - 安装成功后,重新打开Keil,则可以在File->Device Database中出现Gigadevice的下拉选项,点击可以查看到相应的型号。 ![Gigadevice](./figures/Gigadevice.png) - - ### 3.2 BSP工程制作 **1.构建基础工程** @@ -111,8 +96,6 @@ source "board/Kconfig" 该文件是获取所有路径下的Kconfig。 - - bsp/gd32/gd32407v-start/SConscript修改后的内容如下: ```python @@ -135,11 +118,10 @@ for d in list: Return('objs') ``` - 该文件是用于遍历当前目录的所有文件夹。 - bsp/gd32/gd32407v-start/SConstruct修改后的内容如下: + ```python import os import sys @@ -190,24 +172,24 @@ Export('SDK_LIB') # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) -gd32_library = 'GD32F4xx_HAL' +gd32_library = 'GD32F4xx_Firmware_Library' rtconfig.BSP_LIBRARY_TYPE = gd32_library # include libraries objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) # include drivers -objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript'))) +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'Drivers', 'SConscript'))) # make a building DoBuilding(TARGET, objs) ``` + 该文件用于链接所有的依赖文件,并调用make进行编译。 - - **3.修改开发环境信息** bsp/gd32/gd32407v-start/cconfig.h修改后的内容如下: + ```c #ifndef CCONFIG_H__ #define CCONFIG_H__ @@ -228,10 +210,9 @@ bsp/gd32/gd32407v-start/cconfig.h修改后的内容如下: #endif ``` + 该文件是是编译BSP的环境信息,需根据实际修改。 - - **4.修改KEIL的模板工程** 双击:template.uvprojx即可修改模板工程。 @@ -240,32 +221,22 @@ bsp/gd32/gd32407v-start/cconfig.h修改后的内容如下: ![Chip](./figures/chip.png) - - 修改FLASH和RAM的配置: ![storage](./figures/storage.png) - - 修改可执行文件名字: ![rename](./figures/rename.png) - - 修改默认调试工具:CMSIS-DAP Debugger。 ![Debug](./figures/debug.png) - - 修改编程算法:GD32F4xx FMC。 ![FMC](./figures/FMC.png) - - **5.修改board文件夹** (1) 修改bsp/gd32/gd32407v-start/board/linker_scripts/link.icf @@ -314,10 +285,9 @@ place in RAM_region { readwrite, block CSTACK, block HEAP }; place in RAM1_region { section .sram }; ``` + 该文件是IAR编译的链接脚本,根据《GD32F407xx_Datasheet_Rev2.1》可知,GD32F407VKT6的flash大小为3072KB,SRAM大小为192KB,因此需要设置ROM和RAM的起始地址和堆栈大小等。 - - (2) 修改bsp/gd32/gd32407v-start/board/linker_scripts/link.ld 修改后的内容如下: @@ -358,74 +328,74 @@ SECTIONS KEEP(*(VSymTab)) __vsymtab_end = .; . = ALIGN(4); - + /* section information for initial. */ . = ALIGN(4); __rt_init_start = .; KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; . = ALIGN(4); - + . = ALIGN(4); _etext = .; } > CODE = 0 - + /* .ARM.exidx is sorted, so has to go in its own output section. */ __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - + /* This is used by the startup in order to initialize the .data secion */ _sidata = .; } > CODE __exidx_end = .; - + /* .data section which is used for initialized data */ - + .data : AT (_sidata) { . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _sdata = . ; - + *(.data) *(.data.*) *(.gnu.linkonce.d*) - + . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _edata = . ; } >DATA - + .stack : { . = . + _system_stack_size; . = ALIGN(4); _estack = .; } >DATA - + __bss_start = .; .bss : { . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; - + *(.bss) *(.bss.*) *(COMMON) - + . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _ebss = . ; - + *(.bss.init) } > DATA __bss_end = .; - + _end = .; - + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } @@ -461,6 +431,7 @@ SECTIONS .debug_varnames 0 : { *(.debug_varnames) } } ``` + 该文件是GCC编译的链接脚本,根据《GD32F407xx_Datasheet_Rev2.1》可知,GD32F407VKT6的flash大小为3072KB,SRAM大小为192KB,因此CODE和DATA 的LENGTH分别设置为3072KB和192KB,其他芯片类似,但其实地址都是一样的。 (3) 修改bsp/gd32/gd32407v-start/board/linker_scripts/link.sct @@ -482,13 +453,13 @@ LR_IROM1 0x08000000 0x00300000 { ; load region size_region } } ``` + 该文件是MDK的连接脚本,根据《GD32F407xx_Datasheet_Rev2.1》手册,因此需要将 LR_IROM1 和 ER_IROM1 的参数设置为 0x00300000;RAM 的大小为192k,因此需要将 RW_IRAM1 的参数设置为 0x00030000。 - - (4) 修改bsp/gd32/gd32407v-start/board/board.h文件 修改后内容如下: + ```c #ifndef __BOARD_H__ #define __BOARD_H__ @@ -528,13 +499,13 @@ extern int __bss_end; #endif ``` + 值得注意的是,不同的编译器规定的堆栈内存的起始地址 HEAP_BEGIN 和结束地址 HEAP_END。这里 HEAP_BEGIN 和 HEAP_END 的值需要和前面的链接脚本是一致的,需要结合实际去修改。 - - (5) 修改bsp/gd32/gd32407v-start/board/board.c文件 修改后的文件如下: + ```c #include #include @@ -611,22 +582,24 @@ void SystemClock_Config(void) #endif } ``` + 该文件重点关注的就是SystemClock_Config配置,SystemCoreClock的定义在system_gd32f4xx.c中定义的。 - - (6) 修改bsp/gd32/gd32407v-start/board/Kconfig文件 修改后内容如下: + ```config menu "Hardware Drivers Config" +config SOC_SERIES_GD32F4xx + default y config SOC_GD32407V bool - select SOC_SERIES_GD32F4 + select SOC_SERIES_GD32F4xx select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN default y - + menu "Onboard Peripheral Drivers" endmenu @@ -637,7 +610,7 @@ menu "On-chip Peripheral Drivers" bool "Enable GPIO" select RT_USING_PIN default y - + menuconfig BSP_USING_UART bool "Enable UART" default y @@ -646,13 +619,13 @@ menu "On-chip Peripheral Drivers" config BSP_USING_UART1 bool "Enable UART1" default y - + config BSP_UART1_RX_USING_DMA bool "Enable UART1 RX DMA" depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA default n endif - + menuconfig BSP_USING_SPI bool "Enable SPI BUS" default n @@ -661,19 +634,19 @@ menu "On-chip Peripheral Drivers" config BSP_USING_SPI1 bool "Enable SPI1 BUS" default n - + config BSP_SPI1_TX_USING_DMA bool "Enable SPI1 TX DMA" depends on BSP_USING_SPI1 default n - + config BSP_SPI1_RX_USING_DMA bool "Enable SPI1 RX DMA" depends on BSP_USING_SPI1 select BSP_SPI1_TX_USING_DMA default n endif - + menuconfig BSP_USING_I2C1 bool "Enable I2C1 BUS (software simulation)" default n @@ -690,7 +663,7 @@ menu "On-chip Peripheral Drivers" range 1 216 default 25 endif - source "../libraries/HAL_Drivers/Kconfig" + source "../libraries/gd32_drivers/Kconfig" endmenu @@ -700,13 +673,13 @@ endmenu endmenu ``` + 这个文件就是配置板子驱动的,这里可根据实际需求添加。 - - (7) 修改bsp/gd32/gd32407v-start/board/SConscript文件 修改后内容如下: + ```python import os import rtconfig @@ -726,23 +699,22 @@ path = [cwd] startup_path_prefix = SDK_LIB if rtconfig.CROSS_TOOL == 'gcc': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'keil': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'iar': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] - -CPPDEFINES = ['GD32F407xx'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] + +CPPDEFINES = ['GD32F407'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group') ``` + 该文件主要添加board文件夹的.c文件和头文件路径。另外根据开发环境选择相应的汇编文件,和前面的libraries的SConscript语法是一样,文件的结构都是类似的,这里就没有注释了。 到这里,基本所有的依赖脚本都配置完成了,接下来将通过menuconfig配置工程。 - - **6.menuconfig配置** 关闭套接字抽象层。 @@ -758,18 +730,16 @@ Return('group') GD32407V-START板载没有以太网,因此这里主要是关闭网络相关的内容,当然GD32407V-START的资源丰富,不关这些其实也不影响,如果是其他MCU,根据实际需求自行修改吧。 - - **7.驱动修改** 一个基本的BSP中,串口是必不可少的,所以还需要编写串口驱动,这里使用的串口2作为调试串口。 板子上还有LED灯,主要要编写GPIO驱动即可。 + 关于串口和LED的驱动可以查看源码,这里就不贴出来了。 - - **8.应用开发** 笔者在applications的main.c中添加LED的应用代码, + ```c #include #include @@ -785,7 +755,7 @@ int main(void) /* set LED2 pin mode to output */ rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); - + while (count++) { rt_pin_write(LED2_PIN, PIN_HIGH); @@ -793,14 +763,13 @@ int main(void) rt_pin_write(LED2_PIN, PIN_LOW); rt_thread_mdelay(500); } - + return RT_EOK; } ``` + 当然,这需要GPIO驱动的支持。 - - **9.使用ENV编译工程** 在env中执行:scons @@ -810,32 +779,23 @@ int main(void) ![scons_success](./figures/scons_success.png) - - **10.使用env生成MDK工程** 在env中执行:scons --target=mdk5 ![scons_mdk5](./figures/scons_mdk5.png) - - 生成MDK工程后,打开MDK工程进行编译 ![MDK Build](./figures/MDK_Build.png) - 成功编译打印信息如下: ![MDK Build success](./figures/MDK_Build_Success.png) - - ### 3.3 使用GD-Link 下载调试GD32 前面使用ENV和MDK成功编译可BSP,那么接下来就是下载调试环节,下载需要下载器,而GD32部分开发板自带GD-link,可以用开发板上自带的GD-link调试仿真代码,不带的可外接GD-link模块,还是很方便的。具体操作方法如下。 - - 1.第一次使用GD-link插入电脑后,会自动安装驱动。 在Options for Target -> Debug 中选择“CMSIS-DAP Debugger”,部分客户反馈找不到这一驱动器选项,那是因为MDK版本过低,只有Keil4.74以上的版本和Keil5才支持CMSIS-DAP Debugger选项。 @@ -854,8 +814,6 @@ int main(void) ![GD link debug](./figures/gdlink_debug.png) - - 当然啦,也可使用GD-Link下载程序。 ![GD link download](./figures/gdlink_download.png) @@ -870,8 +828,6 @@ int main(void) 同时LED会不断闪烁。 - - ### 3.4 RT-Thread studio开发 当然,该工程也可导出使用rt-thread studio开发。 @@ -888,8 +844,6 @@ int main(void) ![rt-thread_studio](./figures/rt-thread_studio.png) - - ## 4. 规范 本章节介绍 RT-Thread GD32 系列 BSP 制作与提交时应当遵守的规范 。开发人员在 BSP 制作完成后,可以根据本规范提出的检查点对制作的 BSP 进行检查,确保 BSP 在提交前有较高的质量 。 @@ -918,6 +872,7 @@ GD32 BSP 的制作规范主要分为 3 个方面:工程配置,ENV 配置和 - 系统空闲线程栈大小统一设置为 256(宏:IDLE_THREAD_STACK_SIZE) - 开启组件自动初始化(宏:RT_USING_COMPONENTS_INIT) - 需要开启 user main 选项(宏:RT_USING_USER_MAIN) +- 默认关闭 libc(宏:RT_USING_LIBC) - FinSH 默认只使用 MSH 模式(宏:FINSH_USING_MSH_ONLY) #### 4.1.3 IDE 配置 diff --git a/bsp/gd32/docs/figures/frame.png b/bsp/gd32/docs/figures/frame.png index 8125f76176cebd78702cb0bfc2efc922676c6daf..ef7fd7b8e4a4c705903d607e86b35742f208e363 100644 GIT binary patch literal 55636 zcmeFZXINCr7A-1B6B@}uBr6#K6$Jz&qkw?KmJGIl-x{ec1roF0De+&K~@ zMS0D0=kSQnox^=gh!1`uaaqb-JIVE`+Z4cv>NumkW zA19}$WIO|f)ahEXu`&0ZH7!|_6whZglV5&cOHC8`Q*oP>S0gFcnVgA~BxgWLp*7Dk zhLeW=_4J%CwrTXF#C!axakOz=qOf7#MuM4Hbgf~uu6VxErEY53*{EP3jD$g$jsTaC zHQ?O8{j=eZ8&61FbCF#791h+;|6%2p*8PP2kG}>lIq<-rU;gJ`o_#Q&G{E~mt^i)X zB39S?G#U8sUkNUvP3uVZpCbu47Y~~_|Gx~7TrsMpcyemePLH?ygiYHo>?==? zy9}zXmbQ|9_|PXgPAay*TA-b$nct&y_)EJbXua{MH;k0YdUtuWTKQVTknp(ehlJl++TM;7>Y2icv^}p|4{;aheaLRuY-bR5 zoRJzN z)p)Ow4AmBlm{xbZ%1&9Oz3F&Md3i7=TF7dk&9}sQIG?8~_Zw11U!X$?3O`qHam>7g@OF5Ji z#_Xymf2JPV)JlJO$z<0NbGgd0KO@VVHuv4>Qb9>oQS}t2xaJ#t+^L(tyG`3%w#g4` z_&%^DR6Fq;pGo6{eeDlg?~`BitI<*?rEJl62JlJf&6-XQm+yJg9-!t%3>+#i8hbP| zd(7aBetFW9^fg|`*s9WI)D2%OF@f#QRtMWixp_CG@0(jzuOto^GKHUhlOH!vG*THI zU3Znl`c3=pSK3e3)tU_FBb=uZEJu5*Hb(Vsl@j|CgOxgni){B^l%8VO{fptIKmU4L zj16b;tJz)oI!G$9gMQ85)%FvDO49V;5gUl;%=>-UQMX}@Cx)o?5+(I`;@X5__xF({)Pr^=_*Z@}dV{vHR20b?)nH zoK@V~Nqk&N!~|Kmz84!;2F$>d59+GAY~owYmcA$*hCzfvxIkRrC$Cv|dQT0av+Y-kevpst;W>)p&9uo)@#<}&xgHDX0dgTCr_EA+wf!4v zN^8I;!2ViOs=y7NiR~$!+3u67-tHCegTay}tZ@tElwlP*0jZA5N_CvoS05HSQkhHO zH2qAnnUKe@fX!E2fQvR0J+UK9ideQd*@!1jl0V{F*%S$Ap{le<^WA$odVjB0UgV{) z^2d!9VrX6;%1po1`BEIGOIlK%K+8Z)n;W%M;I~#lryWXO$fy1&;{-d$a#{+Or`ru< z#pS+KJ>}K?b)oNj=8SZDcSkIn^6iGxlcQo2dT#{hL06DNY-6f`&8RQ-ra?T+ zdA`?`YMg+@2aUkTi;k8&?C2GpXWXwaKn6;V7wBB`{uaq~U**v*lj`G2mCTGh!HF{slS-uL_=k{@vXpwwJdvbaqqer34$FKg)>Sp>Hm*%~zz3!na}%c}=v}`v z@^=90u)vYv8P)Rkw`^$QjH$hSfBZFC%?z6gJ6uU|pVE8$iph3+E?UaI@6PsL_mDC^ zP1=M5A(Y5XXvjynzG``%Vn>a=dl1ARq=NU%T2O4d zdMIbhw=Em9t&@v8YN`tegdwK5{s}rC3=mtyWKEx2B_SE|YP> z0cWnr2`IV6?Vygb`PGFh@oV(w^G${FuAow6U~dkVVnSxTo1+nbDG%hDvEF|EAgWCcg{` zVr@iv1NDw4QztL63+Y$bzBPBj<12~#6r=aRP=de;O_2Sm38mqFJE032R={UgwyR9HKfaq<{MPo7dtQ& zM+4-@PQ%JK^YdSjNs}CXl`>jlPj{b0HOqTvA-1LZ=DvpNgZaL+^*su8&jx>kK#Z8j z#-r-ybm6(dbft3R_*|j_W4m0r_a_*4WPiq8+INo2i#4(Ys|zL7Fm6_K?JjS-bDxBW z@Gmlf9>o#m1|C+uw|?d83tqgFI^vZjpJEl57dbaD73vI%3GRKk{t`|7>9V+XPw0Ha zLnJeo)!yCi-!*9(Eud4A*wxh$bVka;ewHRNGQr9uils$JklXfQKj z!hR#-SgJQSOvA?SnuMpKxeWT4L&L68zmf2+x>_`vC3Y}$2fms~a(3JL!6HPgjiCj9 z@68BQfN=I;wzpV|p5UMlK@2yY!XO1%b z{5X5-?6G7m2cw8(qNo2e3JvO-#q8wAN7R-ne%hq`7vD(w*5z$ACw^pc8$*tO5LP`J zAdKnWo$cPm4uqSn_B%z!vMD5t(On<4n?Ho|XBo&4)Z-C@CclT58zZgV8U%OcRW=!E zgiB#};=H3CSt-QxA||rKz`tFZ-8C1Ws4D&O91>?A5Bd>Wl9-@#NEx`U4>d$BusVRO zyydoFdHeU<-(>?zSuZXbo)HhM<6stFY3IHEd~_7N_LT6s#eDYJEN~%3ZplAWBvb^< z%F)^MQFI`zKSRD=Wcz*DELCt>yVvgs&py}!Epl3@BUve}BvZBM5y?vHK&{4kqF=0q1QO z(CHLbG(FO+7;r!OnOXG1e@7h(st7MoKlN8w4X)JAr+xsH#8`rXy;YHZWjQI6m@WYN zMWBqi(VwT4qYv=BFlDh$Nh*`y!K_>RC5y4fqcxlOt2!@zpRA0P30n{4hGdq5wEoq1 zf6{`4{+6SZNv+d+3GB|Gu+0eHD6RjLr0=2bTzi!1yzWPjG8>a}Q#49u4+k6Zz^;_4Ua;UG)Wbd~A0J z2nn3pqFlfCCv_ndqX3^<)44;VV~9+)ugin7P?CtlTKgqLku)sH@@(+Q~lvFXnU6^~A{HSyW} z?ACEP+}35?wtls$%6?Mp2*87h-Eb0yC!5G-fRUdZHe&oRRynmN3;XZ~C!oHmkNolU z3sYk3QF-CsXrbOP_&-r~dPt=>NbDfls(N%w7+xTz?JQjET ziO>BV%Ff~D5y}hkq2rEl&f|~uE3g9Zp`^cns&n4mq z_lzdVFUeouV!^TnB3bEEG_dQ*I)>zg>Bx}v|Co1g!Reu{5$V+!vnd)U=ANQ z!wlR|N|~I`kH4eoRL(r0fEN8#^&E zb=ykaa&b1CDD)DBOLmwAPTYvyGpIh6rJ)D4ZM8v5I#J`ul8xaInXdwsBf?GvKs6Xi zQfY}v(^Rk2sgDg{Q25?x`1^Qdu+B6Su<$+Y<9<~0>u0hND!sEz7RGNQx|kJbNci3+ zw*hm$g+R;CsqskAqI6EU!}lZnk2Gp5c zeK-;EvAjChE<@KZsX_S;mLx{&j7%a#c@!R2GxC7z5Xm)O_b{UrRp`f_^k~VdI_-st z`=o2HTG}9<2M97`c67E{dPs%xQt4q5_+xxh#)Xm5<&AcIcm~%_^ZoE&+w=9$BADF9 znpJOO{iqr#<&oh*ap%eIpkX&LjGCa7UjbFE;*JF-TsF=aVYpBSzq;eibke6CTDm)8 zkVqK(?JBL0fkp2-EAX|6#PDMYRDKwAr{u+5PtyEPzOG(HsotPM1hX>)JPU*6%SP_+ zC?hJW!_z(;E$1G}&e2cA+!Q<;-a5XV)+ubSvY7q7l`u;N z06LP0ceoIs1DNlb0;@?YuBzisNVV_Lp4&>%CawLxR0v|VyTM~aXnyV_ux0NOJ52yeJRTMP!FXl z>w8z#%1+tMgp=NYWy~^~gyma@F-}l1P18gUAC=!r>1=?81v$Dsf6IR;R#*ldtz~&J z*XyJM4uddq!{AjBiVIY&9X!$;!|^AQE@lG&6F@u$m7`xx#UbkumQ zK~Lw}?RMaI`5g!)zZQ20;_+*2*o?UvsbX%u9lRzHrSm>8wIavsKsbK*WMGev5dTV@ zUxw>`qtSc2k@*Un1FD!l~&&}+1S1&Yf37#-+BGvWwXh?`%$ne*3{2M%~<^4^LYeH`HTL8{t z)3hMXccYoW-hmLI!~IbU)_%3*BPB6em($EVp_v?bU>Ld#&;Nd4;P+UcAp@sp)YZNq z?v?25erEYWMBIg$x$Y4q-%YdQ47-$6xI|=^fnuejeT`^mIkt7wYKK@x`_`5?HA&GS z{P4y}ecJRWT*TwzoR3K>NBPgS?Z-;Hxt%Czb6Juito4F~cLxV3R)bMF%kX=*VzGdP zTLneGYRTb5{69sX}7X}|Wy9qL6)UenM55(uJyVM>vEl@VmYXSY4Z z+B{JB_JziDwn8O6WT1a=_+e%f3p^i?&=(C7)DzB2DX=m?h+O?A{qI^y{W`A31>%t9 z{qyR-4iGv<=1C}6G@{^PtrE&uk1o4hTBg~iq~Ry$Gt7jlGC@VLk=i3f`P%5nkxg!v ziQ4^L_}zw8>2TwM+)fWG85yybpskN$H*|^8Bg;q1Y_0_y=v)h{eVWNkdqC;VuZB*( z=(W4_=#hz7$<>VjuNb%RXG}N=}+zc~KRH zcaiyGdA{w&5sqb1Lvh(>S_4}bvW3XTy(@&` zUrF(aH%q*aS3dMjXcEMCe_5|9A<7uZuxY|$k~Bnf`fs6^iGpWk%Ha`aB2UNm=JU&? zvBOtSD~OvCB6EXUn*u*cVMiH+cHGXbvdkn#E^K2gWK%JZHbDk=dcXDINspi>i0Ktg zK_j!vQMi7F+BlipmO+K1^49C2rQu}6E+#3iBYGUNR~wpT890~HPAcOzOCG4~2;=cL zsE;Kq*b#0bWpv}NBLhvYWGok?Y?f$VuxXhm?|2Q+aJHG~wLfS$3!q`#=%UV{-&KJ# z6|3r&5YdqL>aM=@Dr%jq$wKB>+DbN0b)olUioUk^sS+#N=gSAh*>r<%GFV9SG$kUFEPi(*!HdWmaJQzSDsYxLd=1P zYQ;ONg9w_cNmp`tQ~D`f4fB_JlM8dy^ECxT#=?Fc<9o2PP|_t#g#eomlu84+V%2Lo z5L42_?^@D**IWPKhFX=y-|Hfo>5V|X+mo4bjm(=M@)7>u>=iO%IDXPgR`nU&6W2(u z4~nH3nV;%a_qPD4z#5JJJo^tDum%VVCn@}jbAdiI>e8qNqKYgzWzi?S?-mnU*u5q# z8~0+}F1`c{Kl_41LgtK(I2XuANKR{pBZ`}dzUPMVPp@cAY$&*smU)beOekDf**wyI zefq5SC_6y}qzYxv3Wv5*Wb4EhO5WjFhtbtqLEO_cz&g0&{s-&edE75#GcxATgnejD zcB^?Xl^mlU4KC`nnk{^EbvefM*x+{8A*qzYxxg*JVZ5Gx>F{S36mY<4%%TR(LH0xu zf+;<7L@x^dzW!^IfKt@4o6p}Ij6cMXTNGOI{C-zn8mtIzur$?K-W3!8yYuN|fj6f>1f&fa|mI3q`g-=Qy4CMbl1l(^yAVahf5zr2Hi7$gs4Du0HKHyBuW`r(jO3vE7y(V@ z=6@&ifBl{5@DKd_{GtJnrdL8Q8ka(9i+}h64(=s#R=$pNygBmF)6&uK2^h&%AW2l} z^mq`^3)l9avz@|t5&33^h*~G}0?qf&?CKV?_13kAT7y8HJOxo5eG>cc_;pJ^RZTc4 zi(DFL%QgM-5>n6Kd>zWuDl%#EW4Hv^+CEaLV@L717dLHzHtITcLMQH47)39{n|@^M zy=uNc>7FKJiT;H3`Oy`>w=<|VUa0rM(BRnfXlKzhib3RMN~_w$E0Uk@6OFCq!bwSd zB~uhmNj(5(u?p()O3&?|Ujgp613Fk0;4sGDTBKTm;@!7>Eyb+(BxvqSbhWS@rbcqO z#AJG?sYiI6&vcdNJJpf5LUztOr~56%en9mfY4Z2q-*)a5{o)%|ii%l>A13^>jto>J zveh`BDk33_p~-ZU+FdhF~y6G%{a_c<*Gr#;|1%9xxw zE;B@#_aq5Ty0)gOad~WhzPQ?TwWPv#@9UQbVvFqKfDM=wu@soP;7v0hL^hrYO z5$D^2rZIu~mB$8lmGMSyU(Fv@+Z$;$0kA1Tjcmb%-3=xnb3^Kt7&j0ScPaE#KT`(* zjF2Ej0E&yDyeQrv6Te@fyg{-|Gn$9*I~M^o(fCH>kxiFDPrJ~G4Zu0S0!mVW8@2nS zHlxLrUq4vXqfh{iaR4&q{TQ5O$5YkJwb!P&wjIFvDvITS_sWy(#%jxuj&YHC;o#fz zYZKo;x-O4!w3~On;t^t(WaGphIX_Z@rM47)gnL%=xm zPVk1(J`#sx?d_q#!D*VvUk!1&G}^RgezrBTCm`2+KcyQuf5w-eUKKrA%t<4JKRd8T zvm?}OZu-jK;8W)axQ}tQd>fGZE?l%LX^8ha+5&8sCuCB`r3OjlcZ~h9u0TUC4+6x- z4Q<^_Uc69PzAidM(pER7P%5%FN0^L7a)R0OJB7{Ha`VWNd^IXgl~S%$j~4#7Xu*I; zDy}+{LubHij+*#a0-QS%$}EU*l^e_C(@9a7*ZCp0im5a;&FLb3>#~X&-UDoiPEoo! z8{{Ma9OY$0NC+z+?60K0zi9kM%D)l2(MqDNcVL}edoJOB{8uHf+ojcBLJ1E9iI z%gfG3ogTe^+CLpHFGcKqZA%o77jlJCNHm@?4dj<_B!tWtWz53ZEJ*sDLbSOU@`Qz- zA)6T-KF%gEO#tGtct~u8;)!NK=X=fvNz_($Sk7eIZ+qv_S^WgCd~U)uo0yfu!zt5f ziJzR!kqMVySFPRY7mZ6%i#rM>zK8*4jW|aKTx_9M&I9|r&oTr|W*{zpFrY+rvHR*! zxvUvkG&toZRSW*prcZclbXc(E$M4tTGj%-4K`cWi$Ne^GlM5qYu`9MLx~&^Eux9lHElbN&~-bR`f^? zrwwvf1W}o!P~taaAOlaPEY*TP^on)EV2%91V-z*%ceGmeLv$$zQ?p!LFGlvO+h%uZ z*nXO9HN3yk*SnhUzTKC>bRXUpX zgUDh|wG*_KhN`?!?XWRrBx#ejtXhjuv*reh?XQq)E5CfkcPez^ahpk)u%eVkYRa5D zA%;f`6?WsoRhNxRQ;fd|8z2zZz=PzIrMm=bDr9E^c&W8DP@m+eo=SZk@w~+; zzFHAC>DWqQFLiNuK7#F~BTh`a(&^fe#om}HnL&kRtoN(c^IVs@?!qkPLYAK7Y_oStetLiw*B98D2i$Czmc#@oJno9h6vX$4d2pHR;znWl{A zVr}QzOZVB*qfoZO{Y zKJLV9{;Gp6N-{4=n(FDKl$Z6pu2(M~`73)f$o8d5Ov>vil$#TJEv*;a{&t?!goNT_ zYJzsImo&|J)udaISViA~K`TURha+GMolmv7XVM-P3>nR(pGx>1x(qrANXd*);_(lo z-GS*Vexu~sJ}ID{9y3mp!EkwdbXWleL1l`+ zS)x(KrTDPUgv;z+b@ZHkiWL_w_p5$Od%VoEeZ9|`Ve>=H8>Gbh|+Aol~X#6Ie@prmmrK{@wb)17elVfLw}&E~W(>qY65 z5Lp!ApTx(usz>f4^j^y1xb4>16FqLmjlkz!7z7XMNY~*RI?ZPK91IUsJXOi1%Y8cu z_>~UfOm2>*IlScjQ4ps)nS?!P4QI{2qvTQo`%-&L>on=F(lx*sy|Rxt~M+zh=qkYWOv4yFiQ*6C@D$rh#}Gl zm{7dR^LA?)2^FQ|hGw*uT?#-Z+hAZ^T9+yBIq0IIeO=j%L<{#*J;55vgmFrGb-m-} zCVX(Ebw!W-rw_2uyhvUM`#PhZ+`p(EAHwOIFM!6=Q>znts&x>%M8O%tV-wt}5(@L< z3D~1Tr`kM-^}$)|Y#SGV`X7>U%e- zaC~hW)1kGrrEIt|c#0iPR&8MhQ`gMnL*s`xmwsBmifUlg7Wy#lcl3ErMT0QiTt;$& z=PKWZ!v?xNLf#RMio1Cto%Jr}c3~k2(o}8-0F+RRZ zfKBpmkkwc&bhR8kxhxmcM?0Sv#XWNZ2fp5S0ghEN5N`e^>r(5 z<#=L^P2pO@{**5Fx9;^yA|&8UCVocv)du-5hXmpLI%w5-z4CFp*E|gNepL@udaqe7 z-`^b~mdYVwY36(yllw$J!sI}LciH+;S{%V_^cmw~G zoMN;!I&J+ZapI5F~IGPZ*Yb7!)Q;I=5VUE_-`HD2kqepM|HO{1bs3 z++4eC_RC$h$=#p${3053v0c5VCsP^*a|JXNi>S35cG3$bN|#QT+77BO9|LE}Q)PAS z6zWsqkb_cb|9PLWj40OKdw8er3bQGPRKk2QQ3(+pd)?QXR1We7Tu$p>Y+qJS0QIt- z>@nlncG&`iTlD=144|l2ld?~(mTj%k5v>C&u)s>uT z2Fr}xsFR>0SfOrNi(QC_`!Z&BTc#{(! zj^2VglWYK)8!4Dx){1KKEAdv@ zf3R`F(>-?jv7+Y&RuWD>X9iM#s%0V8H{%&2)~J8p_f3`!$M^@p^J6Bo7`*cjWqo5K zPYiukIQZ1fLlc&`hvr-(k?ZFq6P3VYrLyE?e+G^VAzmm{)ImUV1t~Liftuv*xj;&Y zfXc7gpkX4v9HR{W+HlF)?(DBCAo?VkH_W;eFP+c{eGf8?>e^xeWQ2qI>V|lm%!})s&RUF zwkmvZGcmr6^^2q8KOF!J9tU1#!}T3&z6Js1btV=78Y10;``+AW6{uUdGI-RsYkcT) z`(!iPe+>A>myM5x0T=3H>C_@jN&9^j-S2pIO+rBR$Xi~wgr*xH{R_{DhW2>f|I``z z33xysX=SUFCGZ=xi^Vt~1B0R&>}#5L+0t-d%Dby%w+4Y7G0_m$0DR7Sz`u~Vp8dn% zZ?Z|=5G0dt=jFH0B5D_H2SOJ`(s!%*;pb+MNOis;bbis&+K!brXFo_;;%wG2_IwZd zG0a;PcBtNx64$vdKgn;2=^s>+V$y&mg`Vky(x1VN;r;og`ivI4!WvUhimE7{H_#;y zM5-822{O?#I)1|01BHTanxrpep0KhJ;riRU$a){#M-6%sOwid%L*= zfNvbCXf50aRYjoE6h0FB@~laWx*FWGr_oXk3g8aHWm$EQGUZWZq4b4(3!^1z{Kg;0 zprXv6#xecoG^nJCloJI;vQ-%XH14_oLT;meKGnOp=k3iesUU6^Xyv>-D~OBqg$65u zGU%Bs>YOcJ{qko|vcY_B%47);3G&-Su_thS3;*pNk#XQzUIn&=O2Dd&*?-);S8X*1 zl|{miLw(|)-Qe4iSJN?2&E^t#`2dH~2=?`U3MfcMcIE7dnGZi=ggm#*_J0i*=orLt zsun^*VG9u#B(%LN^S%~`3_Lt)XK<*g>dpY=@TFw}F34C35`Q9CsM?`<%-MakqKI(P zMFV=Hz__6NNmv8Hx|Ujk{5Qn98{UzQpx%V5+qZ?pj|S z2|N*a`D{iC%c|_g>m;aw_bz-)G#J^;lk@IdW67skR4}O%j(mgH?yE4^@<`E#&ABh* zz$Y>BOTWSrX<%Rbp7?@`aiz?U1He%<9o6nhsWX%`9$N1=F^Jf&;Kuez9{uI3unL)3 z>;Rlp?mqaE#;%17Z2tko3%5jZV6I;+`@-CVnQ~m3zPVoxoAm*+=a02aNY)bUjry5pUh_Ags&>fV1^4BSOG~_MfyHE!4TD16WBKKxP+PA?nx(<{1d4{zF0y#B4H;HgE7VcAe1=$St%zV4@{yI?h zR8I}|Z8sF>8w>*Nx1cT=@GuI3-jx^);|DLnmZgpk;MCFY#sbF+q|X@DdRi%naT#im z67M86%w$PeX5{Sgt~UWbVzL~^R~RV1ku5@_hNh6kd4Zub99N$=hMN!V6e_+}(+aA# z=&0Vex#csTFPhv6CDzZ6vAx-JW}#=aRKrEcQQEg9pF;oStl8ydrXU(VZxUa90qpBg$(9{5u**AQ0yy*FM4$v*MC+ibob0S~lyZb4u7;Tt zE|L;cQ!nIUvy|d&lkKXWCKCX!7l$yuUuLUWH~H~E81R@~5B7nK`VAz<$#fMt%?d2O zW+flDo)MFPMDa79ojNu5{$;;Q@^5THeyQAT!S(mElg+DIPTY$}k8>ZF0c&0D(j~|~ z3`JEvKmf)lBsM|;_Yx)giI3N+ak*Tat|}u9;YxY8fB-A{y9=-&^(sDxyIzvbKsB!` zp>n3Zp0PB^rx%(N=7qtK3711IX~PKgGcriX=JqWKx3SuiaW6|*PrQI{zhryw%gw$! zrs0fEio8AFKKz}ZzQ=>mZcK793QEpS*HAs%+MF!@xfRE`nJ=GVyPha#GSY@j&Zxg% z1r(^W?R$Q?4Jj?xz`gSkQWbewdxVOkf+5!#7_Fmmv0D!2>eo@HDY;Ip{hHw}(^uaT z5)ZY5vTXzypwQ!tsUF`VT|`p0&r%92;GSB7IxfISAh|5#S_~gIluO1@*K`zKw+5M& zJQzwQugGqy(Bb0D=R@02?Q#Z#3{l@hwwo`@D@yTgQTwk~Ag z$WNUj{bAKqchGpF^*(T&;Ei76^fLUF@X7~g{0YzpwHVm1wzWtE-&ccahJW9?^#={uoD z|GGO1G8$?rpwagT69gl+-TK~Xf2GJ2YP*71_heza2|RI+*So@aFnrAQ4d99tS)D35 z_iZMatZHqt9@yc0~CmfpJ5=L zJSptc7wfOGGtdc)$zvM?I`FmUfaL8*(Er($5zwx@oxei_cBNuwz?2ur3*nR&L(A(G zdv|yh0L04OiE~4IQ{wsK1qh+)aM7J9u!VTsWGR2YntPi(fA6I&6@a<=@L&9d)WEN_ zXsykeWeS_&d~@XlzD~EB_ZygzGFf44^HH5Hx+rs2$lQY+N+n_Zdq+@10QK@qUS9|> z4X~r!I}5ZWJ#vqIo3MMzgERxq^esUhUpzZAKw1D2i1Yd?p@iv0+0XKn`pb8Dz zwn#9g$8?Klu6^m3(3I|+GlXpS5gDIErhQC-iBqT03X(K@f!d>Cn{PvflranEmU-pcn0vfuY>J^%b;Et47N*_+@pakC1H<^nXx>;Bz6VmG6VR@^md}+c`2*NnjsA| zD^w{|XxQ9YBmv`%p$#-{@cIh!Ka04|>qOSv*btc2rM)0gBBV_71r8<|R#V*P7q3+T zKl2#zwU3X0Ew^jT6{P%MK;@0;%TySL?!g5jM%N(?$cx zMuacxCbhTj23UddKc&j2GylN;>%kB&acfg3SSD?a}py|7xq7hB_qc zSIVD90gf9|eKg!FUljYFo~)hRo`2^&(MLoK|5c1~Sfpg-Q%q!^hvF_=@eweumC;;% z*yfdWiXLc$X-N2;{IW1;^7GYBR;VxMD}_Q8P@iJU3Z_7BpfHfQ+)sdHXTBnqm#P~# z_gkw&!d2>A79aN{i@4`_&ZoGqk;-(WXabPf=OgmC4IvfHF&lrdQ@uosD zXpdf-H+!j7Fz_MvjS?nR7Ecj<(Vdp zz2 z!XBM<^MZnLq|z4zy|sOM5NCy{6a;nr`BiOcNIM>beo`RnRg1E`9D=okz~Ij+Djp!; z^3J<}O5DCjo>CS=OL&+{WK1hN_S`2I40)7H64R$oT~(V6-xq#K>D=iK)o5sa`LULCP=y$%8l^7R4K!=o;b3qqbjq?0bc6k0HZn+0_D z7C-~&Qq8i{qgF@AaB>DT5(7$5o9MdBg8HaDd*wW;3D`eWlPwGOJ@MG`~W~XrV8Ndkmd-?9iIb7@9(h+ zh34G}97!3Hs&B401N1;tZIg&4( z31p)P*O1~o>j;3T#aWE@!Pi%T5^>P?u5mtHe^VkN3Uyrp!S40AcoQhgDU(elyPj`( zr8O2C5|S3yLseWF4ICPVzy6y0?G~@Op}j$Qe3S`~17qUXCbzSntS7eL z9aY@ByC+AhRJ@a9Fq~9CcV%*)%crM^X!vn(QTbug! zyQimA?V#BexKDpb)kPydbJ?&A9sin7v(NhrjB=(Ws1)ZB-A&10XTt=&tW0U5rvRBd>1C}d)>w80VEFC; zhVQH{mc#up&Wt4LhoHtmG8}70PBnPf6D0%@Fy(2}wmC58a*d0naXNVMu8wDO&74H~ z`j`TlubXP;wa&lEe62MJw6vBi=Oq>s@~U^@9%JhTZb$A8vtT}z09kr%dKA=!nKt>H z<%cVvSeRQQfpIPMQ7ACZ1`(tfAb99S5F~v16&(_tdx3Em%rk!QAKo-N6FaZ0j{j)I zx693YB#RT~ungeB+}`VrWIb!1zc>;NzvW+cxduxNx4d~jl<<${cegbN@HB3jT@+2) zcUL#4JpB8(BQ!!oN-_v-zO8r5n;s1)U#ndr2^Gk1L(i@XF*iqvw@wB7kOsOyq^Ml1 zGgQ*S*f;w8PX;9>H^WD+7VHQvg{S)b@}+fYGFpctfKnz zf?=~#6DCtBC-tMXW{%)59d zE0>6kUh&JJ%kv?VH)obubsF_L)X&cn`G|EJ1V;=g16KVOkDFU{G%Q~rn64;?;+|Ml z-k%g=KAg_KuTD41)lojIN#dIW3`a_*b-671hcnY5v*Y6>BkQE7uUG~ZbgCbR1s}dhivSKJ z`^-@`YtP{OBXRuB8)|*Kd*>TCHQuiy6EC-gv-4s{Ply4lm2V)B9>vt{?4h&zd}jJ! zrZ1CKHa&s!2uM6L`>2g+sQ8@W{#p?2)KTZ$Or6 zqWTjR2OIT;jB0hu6>ZoSI9Xr};Iq|)3k&!F@{6tm8%t^xM+Gx*jSuk;CT zOOy|-UiuXoI2m)fE>kHnRnx*rtM$=MAfz6UknUQynI&(=bMbKlp%0~;0mu8NP6&$j zJw8Pj7W2$~-5ZrZ8jkoqTeQ&|tFpTeBmA;Rju~c8+uxuKAb;wsZDh z6*SL?;fdEtd-9=N8sXMl%1RRlx_D0U$?RzJ%o*wu@`aAeL$udrB%}W$w{+~6O3Q5m z&&%7XB~)bGiRsJC>#&`Whc;w+2ER5j&5 z^_xLcN&sCZX!!{Xct+xs~ za}w_63d*Rhc5g4WLG3Ax`DvJ)4R92Ud-6C3@$LKd)ftSmxs#1;MyBtrFR(m2*z&fM z%_X7Qt%5ZfHmkW+vdB7K3MpAZKZ!LDJ(CEx7pBMa@L)^IAn<4d;hBtB^9Ce@?$wc1 zu1LpgHj|Lu+*}vzjg-~{D9D^>(-|sGI`H6^`3Onho}5>i4Ls@8pu>gZ-?IAai8T4^ z=hnI?Z=c?GqW0wl zwH^4vDyZdVpUdL#JM^a?brTR{cGMl@H})fgc=>6drD%?ky@aqmc-nv4dYULjjsg3= ze7gyl(bE>A@SDk%=W>5gUsMPdjfq$Q^*tJC}gU)#m}negH!{FDF>*@_tH+ zRq;)LM>%~ER>)(9cgEl2Kv69jMQaC@h~=#6mOumQsF9B)0-cE)t*Fj8AQOr=a6V1? zzD(oe<$eqR%KZHmY^*Jtr0VwyswU8}uyC!$BcRp~w`$uc3)MNE%Ssq0((RGXIKQO^v~`xiJfuTx0bd|1 z89@}M1%h=6Df93~4LIj7OZ8KefCkOQ#tb$)u6cRF*Ffq+F0YS7m&7|eJ0JoQaVy$`N8~|q!|G-F zYLWJr>t^Kr$>7nEaoD|=jBn$0Jf76`)!u1J2)0~*KJap;fZqA*$TMSuk^;sXk3$T2 zGk=g_Sh4_ip^@O9R$%1^TgVFeogHE-W+AGhS9c)pFYtp|yHJkTU;N{{D4zfJXuVzvXy6=4Tw86U2~f z`3XP_`R^IXKFu~xD4{c6=bs|vzg*}RN?^9iXhVF6hG5MBLl*rp{|y@Q4!C@V z2xkSiKKNxnJ()hlX8d<3|6P^;J}XcN|Npduq{|4QlfwjRW^n75@(ZBq{_}v{;afQn zsTjXGTS0s98Q5+bj5HW(4)9CvD118^){mb6rQ!f2)yngvw?Bac-sn%BQ~df4SRe;L zI#)uKI&|1kM8&fw)a4L&8!g}q^=@xSxwDJGdsR(nRis8RedjwdlRUq3{ zL&wxXI`+7AL6MUm8Rv%`65w3wknAIi4?V&kd`O91`XFC4mPvC)BTw_a52G07odsA%PvJ+mE`q?; zQ2`buJ5EI)A|eMSM(4O~M?|bK%KmES}$E*ZQz{ zI=(>K*08no`+p$qo`6yD-gv>{yAwMJ7S#=$kyR6^0*-=FQIom$aYJ_8{}fvU686KK z2TUS*^*|X}{Re+H+dJ191WC@MqTgep>|>LJY!WP|TSAE^YrjM>SP(F|sI%MWnI$wn zO&a56R6m6pjH@Tzl5fr`8nLPX^mPE%#`$Mm$(97D+usJBC%^!;vz0Pr$l+3>#slyS zIkjvGK`>4oWIMR4*`iJz-v8pE#~RnW74@V_jKg5SCUA{{7CN7-_>k3u+Xtle{sB=T zC8Zra_r-zt_TT&w&h3(nf(Xu*|mmHP2o>pm0j z?%XS7fu}T-@Ef;?UbM`%2FWLASejg}ysV-dliT#mP!F}CN+YKq1T|7$9B>=}XTJd> ziie{mbS`2HF_?p4u5*tMWdwlOIk|o$RS85PMtz1OcshZBk~eL~u6zIU7zCpF1e)A7 z$r{7UU*F{a>lB1m9oi5gVr_}^@-1-e0N2B}sCnE5*4^;v7Z9G1GdBc1WviFX& zt^u>a2Vkbh01v`rnaD=K`j6J3#{BRs5gga`BW^i!OZv!{#SI8Q;?ck&jc3U2HoLaTxF`kDP$9UwVQ9LFG^1+<`c{mspQRTfDe!E!6|E zOLsNpSBuZQ+_n#{@c}Mik(A6K=7=JT;DBxpHw-C4Or(8kJg(DrgiHkH)1A*p?H?;f zOZ2HZ0Uk%lMpq!E%~;dJ07{3b4&M%-l!G)skgT5T(!|h8I6~K7?G+|FYy)+>!X3X) zI@Pt1K(qdvT2sE*q2cE47#Q8iF%|gfGTV26RJ=EBcsHjTQ3UDxxcck2RbWkM><17k z?cTZq#Ymxg9eImKgdEE_(9yK>_TF%5lA|xCpq9kV@YBCD(`}7@7{M9eC^(vYf@?eM z>BXa6IALZ^?2W;gtqTzX<_EijDUbbcXKt9wR#KDKyYZa%*i_P2@3w_tCOAabUc0+> z{LFc_Rj)(~A}`25T&|A^WR7t7Em)}<>pb6YlQSBf9FWef?6yqYXB+!E*}6jf_jp60 zwC~>HFYmdCTZPnUlL>2Bv^ioM8H92K7vCh^&`M2?&i`gbm4N1P=m%=2oVKxIg{;88_IX42>e|Eyfh z6^u9>d=FGUeOI3#+0r2JMxAP?XS6a?Q2=1_ERSTjl+|hh_d3n-sk;2EyJ1|&*_&N? znUK-p7$|w-;~mDuLThH`MJegMx|-ngnwnkyLn>$M&clca!Jw&JE`hwK$p>sRz4q4f z_35N09}#zTcu!$8cNub#a7%+%_2w;HK(uZ0F9MV!6VHrLkKrj?DuAn zBO=T)CqDQcN22S+G}4z|=h7Y$h-ZgLZYKJ5^Gnm*ue9}%&_GCdUPY_?3vutlPCssx zw~hGzijFSXI+dgGgHqs?&m*hnl_gab2h%8*#sXDe-Xq2#@cfcMpVBsDjx<4BNB+6A zK{jm17n4r*_qzz1pYd9~&lZTNsx8 z?k?^GN$Rl+!$IuNwzn?R^?q2DSq)5;%G0gUNF-KDH6eA4c=uJd2>OhWmL-(9XE=>V zRS)}+!pk6)3@bqH6`IAdQAVjt$D>V4e$O~_kMwoVFHZ*IWLBj%&nIme*u16kK2K0X zXhRBH2SR6p%pMiV3tqe`hog8@Ydl}qIbzA`DL6@4(Nu%(N~{S$^7q0pE{&EmCrPlGoz>8Gd17QFq~m0U-&%icns zJ+~h5-0E1Su}~~pdeK+Obga`eeA_a81CO6qFysHcc(h;TxxvoMeO}BwzRD~DU3}J{ zI9Sl{#n<$DJ$k*IB`?KfGcnBb*>o+Tt8_%eG!%whmU zW^}W#TL@{mkG>@Np)4L1Z^F^dE)~7((fItAaUi9iPv$bW^?oj>T}eDHY+oK$L(YRvfiPgZPD>bTq2OrSHo6uhAXpqry6D6cpJj05b+9M6Lj z-@fKo7zDO&eb%5@n<7%9p8)~j#3Z@jI+A~}0K={|%)K*wGe77!?l%>K7Q;kIM9`Gu zYtP{w08o5-c_g_3x;$IYbA2@N$EwqShci9b=5mLD&9l@5jO&R1I~$zvEzTh2Jv5ca zW$UYhi!!+z?>r)VesI=0M)GDO&7FZqhI?YJ1Q`~4#^TO)GVeIEhVQ1<$hRRQMHac{ zWKrxbG@@F%0=_@%NVkNF6s$}=s4tN_U zxgD*{edl=mWvd6TpiJ6ElGh27%`_SskmS6|*O~+nd?+bRp8FNG?EN4k(`m0k!W!V$ zN>7lb2Hg7(ZapAwBwJI#hht3DXN1a_mAh+{Jjg+;rmhclm0~ar$9GfjY z>D*Q9=n*no+J%p{hHoUx;}X`9_`y880uFVt0EFuCM_#lXdMnj>nw;#w+XHOMhJ<7! zd63pp@C4-%8=}i-%wxsI0Tx<&h9^AEBjhwJB3=@ zZRJ`CyVoa1Eh&1ETr0W0<*OQt#nUB)s&d#-v2NjuxMRsa55)H_x~P)p&H{AmLdFsq zO8+6GcJbuet*0pE_E~B=CG$%4azpb0>-bkwHrpTBUTgE^uju0#UO1XjhOPCZOz?V%Xc=>{v5wf=`*58IU-GF^EO5;>L8(R>EU1 zT9%pdz)=NZ=7G&T{;3e{nLZ$F%Gnu{aN8W=O=ylM;bk#`&{;G-Fz^#v1H0%U(OGdp z<2xUGhfM}PZ9LFlSpt4qEdIrVPHl$h)aGP1sTl#cZYKU>j!*X;12qDw$)T8gsL>Vp zlN{UnL%*-WGgW?i)Q;DHc!59~?l$g-#Knnfus%%MA}=}MKLn)h81TEg0y<{7-Zw*J z%P_>9n2EIixCu{Nm-#C;AD=Y*zuoeGyXF5Uqvbw;7OX*EbIuAh%<@2NKYsH2?#$fd zJpq$l)|A_f6h<-?DSR@8{X`)_Sydpz`5q7{8UCPvkj!NN{VcT&k0M^yL<;K;(|Oc> z1kqHas$n~(ooQ^&79i!;D``bK6V3%lJYets!(oa1^aJJ)IME}=18d+~tAnTlLLI(` zlikOC(ofJjNCJ0|y{l|?5Y44O{H0lUDztrBqf~%m8_-$hf@;nJVPhI_zU7c$X$PRj zK}GF+i*P;H$poZ^$p~8KC;>CBxD7cX>+i463fYfcD|~+&0NB|OxwJsMZVbrV90b}$ z>Ac@g&3n)?p$TiiL&u+!!l-#!M0_Ih&cPs=Q8!4}^zK_0(A^R30QEaVIHoy4KBF7Z zK(`?PC=~>|hYm%@jvasszE_HtaDr~u0Rr!B>j)4_hN^Y_rzb2*npDA0W2yhcf?8sP zWd+o$nWeD3gh(+CIW(X{eSOT}V3^E-Q>*LEzdp)B@ZbZ`qyB#P--@N9FLmAn?tijK zRl6Qx4Z4tm=*xR=?Y^Eezi{#-etA>?$sg$r?h7>V9?Dc;14aAcOmi?d$=a9V$`>_0 za8&Px=bZbxxqLNYxl3diWC)LRQw~C~mxJI<2LJ~h5|QJ+ZWnp}UaU?Db^yYV{&wKV ziT?i1Zw*-m=jaX>eUD|e)nX7c=}C;Vu|Qx%Agh0i%C#H)I%lu_t_fsj3)kab(jfYO z;ty6wGn%?;-+ek;8_Rt=?JgpK^okXSoX{(Tcw9l{_LZsCZAF^D))Q*--y?+^wp@TQ z(s#k3|4+^~g2y5Ql~8E?;SF!>=Z``pwHjD~{R)SllWa~K?BsyJT9+rFAVbdZR;=9u zhP!5an2(V(Xe1&xkvVG$z?9@NxlY6Y5I^CdHE7PSrUSgOU?fzu5_`8 zWDgNrTm?XBZ!t*0k>{E=IJwc)DM>%7kExP!I}DNxAS&C55Tk$v%2}E1DJ|g2Qf5TL zlpSM0!lR}$p1nSD5kB32J8Av1+X5>wL;@PB4JUSA0#zG*^dpE}Cz(4@x42pg* zrf?5tA`65teONM#&rV#`J#BYGt1;m!y~cKC zvpWyVVWe})y71g8|Ed~BTmEjFnuZntXK5ZzT4P*KSA!de8D1U(2uUX-lB6z5`w)`y zNG^P%Iv}CP;}x!z*lPQ0jt1a)<7v`pl2pyf?`8qa~AM1lwy z(L9I!Xdg$jW4(8c4wyY~Csnz-9}j61dF;z;c<_>HV$usR>$en_-1Z)K{Smtp#c$##{^`iK_9Z2L~<))}JMiPD3Of{uUqz~9| z@CL&Oe|^M=ppXE%^??*D#e_B_#EUmso6>07oFzuV*6;LD(rq>IR10kq!yN7?PoAq6_RiBxhr?kv#sEfS_* zOZD~I!425h5|mTKxUJ4*eAt1c`k5$GAdD1%{_&Tso3>{f1AHN@bg<=V92y9~iXTDg zzW#`?6cdtaz&EJ{?_`#XdRJQ1@0{N@S1L^~>)^Qh zEo4+f+*0r)IPoHF4uK=up6!s@mgT)U6lxPA0_h-y>@R%eiz4fz(04!gywO3uX9R$;UiuSfF%{Zh4#QviH-)zT zRa2$nd<4JMTEcsVC_g|GuQOQ{5i$@#iAv!HJc!(x>v#^R9`stH&g%`-A<)tu!Y|O& zGsb&+(T!E%Qn|KXRl2{I2AziY`B@DazbH@-SDK?lq=`WdECBu00coCgBQ9Xz3GtX% zjZc*T27})TQIm_18K9D>bX~SU(oZvht}Fx~P!I4xUl)EF`UJ6#CxQQ7Sd&4>vQ+yC zvp8D%y)%LPFc=v`_(uwE51|$uGuC|X13y9t#sxj?_b5@}>4jcs;Gq)IOyWIr9-ayS z;ZEe-&;f>#0Y3j;>jDgwGr0*@Uv&eB@m6N}igx{AF*R&snN?6Oo2mH%+Z$^bi66$> zijHiToeLfEQx!W=OBiyj2-(~qM-MXn+CTunSwXb}k%-6gjEasBlKANi!i+CKDqtYJ zF1pS!moAz)&QLSmCp;|BDHASnh7Q~W2e<5gZVl7{*R5_dmMFc2$8UJCvWC>{3A z#rLiZtdL^fm!ETV4OaUWlAT}_v@ixu+8DL>nrD^6Ik-tw?UfJz`Iu6ye1vjLbciqu z{F#P>3mzLw*+2yvOE_BuBvIOeDk%QUK$eB~#urfW?MS~(74MtHs*o{-wA3FJ+X3+jvZ>JO9y%%>3;Nq zB7A)CD+l^N7aGo~EG$4*S0EXG!Cn5)&)FkCKatQzRUrj4J_sb@`$5SHV8s!bPu^Lq zXB4HS|GhyODZGI)g@&%kO4vlj;b|9+jdCYBn* zpf$(@<{V|>KtFS_B(Zr6uAA)0Kny}$gZLUKTUSQ8FMjbRfJu7orZUyP&bK9$W2AEj zDfvV}^0GK6OC%P0ptVV=0MmbeB;=qdt65ANP$mU>3YR@RY6u5Z-{P6^sMA2+z9|5+ zc}_R0LEw-K>jI(l&N|J~BBsLo6zlF>gekZOrl6O=EueqDhh+@Y7_UkIZZW)6OZE2~ zztJzPB)H>eEozbtmJ8t0q={n zB(A1n6Qid;nEHtPn`_cA*Wf1I{FhxojRBF zCd%EVln&|J{JS0s3#$ zS1EzIE=j7f)(2IggQ(e$$wKH>0*4L#_2VP|{(cYP1)wFv2K0;l^DL~_6GqYyDO&^2 z`e^_QB zH4wufmj!Aua$z7!Zv)4zuaXQW{_FlJyZ2`~Z$roJomr`8RE{gR1PX2ebs>{+Pg_bv zE}`d{Ez?r>s^g-D(NR{7`M4e-wbNrW{p%Gs!fJh>g4wvSI?uw!AY}C#z{lq693$I* zyYqi^kI!*sZB3w&+|em^^?378C;OsHnpRv+`02uB6B6>0OUhsvaT|akJkK2yCEO9K zAL9RGuOh`-ni=E` znF&Z+$-ff*^<-IFY8#`~82wccmEyVls3q^7qGc~uzWMi}%SGi&bRVuun}ITuVw8wr zv}!Mk&UQP9RS6~@glw)$Mb=crc1P&SHrgpy)?a-)*7olAk8?POv0Ikyc`s*kJ3{YW z2o;ZgBWSDrt;~*h$5BtE;2X#|o@D7bH|er2#+D4cQVyWR8u-b#Pzq3Z|CO+Y)9xAs zr573Kta^*OBqGZ{^uJw-Q{0)MkE}GzpBxD1GpL`M%?io4Qtt^pUz9T2VRR`?KV7Bf zBrX&uQ80eeGji!mrgnmlpoM1b0TFBr)4jVimRUDLie$c(ldqTC%!JHW6hAs`Ka=h9 zjSe^TIecZ2QL?kuoO}kyq9H%kW0*A6?ozqYzEwBYUL^fP8Krwa8Ex(KH zAiRBESBPw~w#oD|g~aB3gU~9@AS8=*vg5)WDO&I=w`Oe%Zhd@MH}C`w@g+{P5&f8T z+P}-u1F2*b8$q?QWpl1I+G;IX$$E&d@`T4)>r?SEOB&Jf`O=7H0WqqcpQ4cd8TM>MqF`7p6gP{sCBlz zb?J7h$9uKkBKK^Qlns}j=gy{#SK1B9=iE+mZJT*~(>a&DMCh#J%X0Rp#gtjMcR6Xx zVhN5vwX>(G+*fO_OiQkb7iLsh6N!}gA8=Gn(XGDYSs@TdPL;83?VGN%d$7044*%9i8N#OY~afF%<>TJV1wAE%ZB1L;L(hD35UsoE2Q!oql zNxaGCOxSp5r+d0|ZKj~2f9+KQ|D13^~*B6Oud|og|5<>hTkcBS!X zjS-FPUlO)fZSmZ2$^Y>#w^iSB#0}>QLN3(fpqEzOr;N&3BHXVewYkjJp^C|= zt==&E`Nllot2m{cX!t!_u}}{n2z2^-gE69f71dUBdqzp!hU{nyLUC=ag;q>2j+U~ zA_P(=r!rV&?bpTk=}o_`jno==)T851w$pR5N=YC zYacsqTDLIyv=XSF&$n{!heTGyK0Vnlt|ouvlC5>Jh~)P7qXUT|zasjXuH>bx4xRYc zu03x#;Mj6mpbg9ur{prOYK9%W_eO~sRB4xiApXHI&!!rnEBa%W_W!=X9`6O%EjOE- zq?xs{?##+F-p2_V~x0h{%E5%nH4^dJSbP+d}E= zA}+{hLgcZ#Rbt4IRsVb&t26(n$%BrR3zk4rnY~A|+BObp?+m4S-@GPD^0;W0wI}0xTb=do zLLv8GZS%c#FI7WjEtTCjyN;C(Z+t1JbyAzHVB7cRBHw&t3DGNETt?e_ty3zA&F$(7 z5}yV9RJF%e?JqrHw$?E4a15q|$mE@ksx*M@R4Q4c|FcDN9)^UDWW>2TBk37N3&(of z3Ma4WJlm~!%Gdz6%GDvl=^QWLqT0oqlYXwkkA%xSSKE8KqJ*8!QN-}gzFuwNDqR^% zS(#m}ENNL1!i6%56uV6RIuOEp|90~er|#g=4-|5@L?8C=bWHeuYZy44q7>V3l3bD2 zVQFqPBYn-Wyj0f8w8u@9xxBt6ibz!Jvr6~1m} zE3s9T7cx&cF$YQH(S4|V_htkR@#C~UvMf_e29iICgwILE(WicRf9OW8>u7p`Y-=|~ zVIMAAXCb?XO)-7I#O>8#Ich#t2Hf&rEWlw_5J}_2iQI$p1MhKVPAU)N2FmQQbmOLB z)n8*F2$6eHh@9u8Ty1h7N(7s}Oi>EB~n`?gV^C#Bf?WsH2PuxP(#jjz(%u2XlyhDWdKfafKPM{cSS@5d>1`#SFPe&#>>|CC zzu?iO%5bIl@v5nU8mBH6q)V`gCo0S>5^Y3`9 zO(#r^tA*4G`@LD6mZZzWxQO|9H$5)>!!eXx{TENdR&y($( zA%AeGbX2@>E9L-(xbVP)SqNk6f=;X7IG9w9R%Y0bn`zgU`%*eE8CG86I>11HO`(oB zHpG<8POYBaZ|GtBHm8k&Mw|a4xnhBh+Q~V(;NY*3SJulc#eUaxoJgej5P)fFc= z&WGUy%RYyLis1`1#A_E$mR#3%lesBR>$x>r^~tI45PbQw2d&e14%!x37zm$ZD+sx2 z*t>ekr`h98DZ6ri^2J+SU;3_k)bR=^RaP$k{3$NeP;4rbU`i8zT+x)TU&G^~b{t!{Bux>nT%velVn;otmQaDx2~o@!CZ5eowp9ceqew-QJ}IV$Rne3U1BLy%O*AW zfNixL4|9q+h4##iKze-0M0-p%J!hFSka7o?YhLbqi;^60bB2I`bN1r6_Sz7gSbjvl zy1y?R)V`4jw-KNRua!t9?n=_)k9$%Cu!a+haR<#FPZTMW=;DvOezLW6tj54I_fe+H zXHV^-?yWQqfLa~5#m#OPD!kkF$eG>9tF3ksU(LFXYg3xEE*+~FSY6o9xLTv})FSn_ z%jc@=>b8N_&(z943?${Y#kGf?pX_|;B>$vO*Hm;xd3^0u7<|P1D#$M!6w=vZO4E8Wmp=1upO@G4d%?3@ z>YN70xRv*9PyRCK$~-MB`!IQuQ~UnS4h`HSe}Bxv#6pH*?@pV-BWY(3v-yhE=aB)_ z+8fDg?Nj>)@Iu4Z7 zoe=Iu5|-t~-_-U0(pmVkoR1`fXfiwbEz#g$^;b_;zgzI`%<#REryEKu-4e3V@Sb3A zyKc5*dV74-@?I_I+w@vw*MRPz^AGl&=GOAI41FG#&vMe$HygZ6D8+>MbA~Hd3tV5( zotT~&$GyF-i7j60+iq^%zNca-yv)`gBRtw|qinm7-)U?fSfE}u_*jTnpmFDVVbt(! z0JeU$N&+Vzu(^Y4E4I{)D8n=9 zgHU)v+xQxLq)zmsp3<9lJhEG755(}$@QG$dF?p#zs;i?+kHX&Ia@9XnA}~<=vModF zW5t`&8lGb*BM=wvRNTIJ!JeJSKxYOrc9WbF`Nz}tw*N@ zoGBJUSv+-3GAp-ybzYn)q4AjdRodxqn$MFh;yF`zU1lPBYqcZeW?EsNh)NgRvHrsI zQCU@`p%;l9KV0pZlyZE#xvjL4X*%B7VXq4E?d0 z4$n(zrL{s%A0K>qnuWc%ZU+&>i4)zH^&Q`4hECpzBxF$BX)G^e7kb-Va)=?g@m};s zMPktXI8ul5`)sPOy%a4ygI5e)|! zS((eqWX0VT#t1W6UnfW9eOk6dE{KPht}dEdJc6c!U3fF)(v)=uUf^AGqu9L zpIDhECBH)7LKsZO)O;aNE>;*5qn*EY)1bMSH~PQk%TWkp9t2{tOW7u7x5Rx*kH76< z-ZHx*%DvXXZ{K^&rT<2^4M}jtxoq;;NiiOG`gxx6dXHcE#ZIe4J0WF#?RU32jb8FYR7FS z3oDsgvyHwEyy(;;8dl6#Rz9=t8$A=yBT;u>8B3T1&`o|@#qFjIN>53Zfr%{HQN3b| z@<@Z|nY*G?`(OVopjkSQu7hnl*gqu9tt{2}{xVNt)?kd6jg_F~i?SU*jq&aX(vBTMX0;l zc56Wf#gV&G@%E_~Hput|_EqG`JnHWA9Qd4wSuJDlKNfm3ktd6wu!4n@jP|-&#n$D| zdDj>s*48DGXy`r!9PPjOpqoskM|P#$JT>aR19^)!bv8Mj{Hs$1QA^GY)L1>bgZ`LF z8_MLEEf1Tww>k{+pQQY_(qmH9kW3&so_xUd&aDnng;rj2x{QLr=(pC|YiBmhvTizx zPTQ8^$PBsExlOH|`ub_#5&r@~PbxiUzVpbZ-DAz@OW#QceZUV`gGsCO&)94K$v?T^ z>qeT``uKpmmXAc{mB({68pM0QuKx-!o&K>RJdmD6Ak+Wky?%5s=D-L=WXG_NZ>DI~ z%6!)I)9>cQ@AT5!{Hj6GsYlQJVdv$I`*E07w${{5n^Bx(Xi5uRXO(DT@$9ODu?T0Q z;7tm0Ppz^~8~fkhGVmx}HrtcA&CU`z`L%R>uBQiMT998*YRl3w^v(8Vj~Y>uY`b-k z@D=v9#S9G#kTBIh<6+tYiD z#jl&0D2cD)3SMicjeOaOy#2#D!&=xNH@a;g+coDKW@G+0HJz-l?!AwPRsg?hYvO>s zBou}FXw5{){<{1?nUfKnSKj)TRK=_wPPXr!f4O?)y&60rT_4t-4V>2u;PIXB5J#`*fw*$kd#p{43&^L@6@ei&qZ z)w{&BBeT={VWs=_K8;U;mO|b127I|418+>{z4Ed?)bEMVk2!b$CU@SQ+T}tIs!4@u zSJQVTkx}=rJ>oDj(`#kqnIP+v^auPOe_+zw=3Hv)!6#f~iULz=!q$(Ua}c)`FwH zn3bB-1M&rht;MB<{q=KY+0V^6%bkt6xP$T+L~~esjJz*CK07j26qa&*mdmLH27ZV| z_%WT67S*58G1oWH!&og%HP4cF)=+PS&%-z*+Nq)A!ukPn)p<|@E!CqIvgRsI7>5dl zd55mOVujf`&jAoyDixWE)_I|D@5N=Q>Dy+eA!LWRioERp6i1|n@MrA;NMWmfH~H4l zmA>k3{9IBqY>_6Vu#Wz1*QY!|qopBdUiUIa3t8zhJ(5r53*i)u>y=DLH|f-EOKm4| zGu1LzaEk>$)qrkaAD`=I?}<>`nd|$$Okp1wDpzi$Z@qK8 zYMrDyrQVI!T;Gho0q2Eh??aosGAnvabLo4c*d^`_y>xosSm&+&V_H^Te8SxyLl%)| z^YMp_WZpo#Rh|r`g%y2NTl*}Qx`3U;$lKHjbbxFGd4^E+4~%I7L-J)^AS-GMLaA5H z-M%PmoTv29)Xa`m%h2sgRb4m8dJ}l-?$y5=;4`!VW*L!?tExIm2$t8QTYUC7HUPb%g$$N)oFHkz8@( z=bJVd!Tz<&!nispP%@WZ|IPF}H?4x6+xzH6PPmQPFW2Vh;fQ&-*Puc;gP>D4egZJ&JQ^AFdNQ)ctg5s(*GQRQVJSccX`(zfn8= z)tQPwNqbSA`++{bi6NHVg5{!`kbPUd`QdFe4RC(;JP}(ATAu9@zLni$Q`&{ni+~xq zuzGnlfPpC+N{bGX_2XYTv6CbWM*mU_{y;wkF!o`kbNLEatCTdu+Wq4s;?vIv=Citf z-sd>RCzhM;*q!Ow%XDn%7YgyoLk!=XbqkJ+7{O3CSt`89-|Sj*r>Z4v`webA1%U4n zQ5ns;*04xc1^_R*v)?}vMb-#Hy#B+%kGAYQUP*6{H!DD@;B>aW9&e>Z#|dv(^NdFS zjn3G?qi(YNmi>7z72gz8F(1JdGbTWI8Flb_@q*2SFn18|VC)IY86b-cCkDL`+DiN$ z&NYJZVSxI@RNBgF<&L;YDWEMn?Hj~3K6Q_cjYPO&Pmvs5Kh#)9NGJB)mhrCh?vz7L zwopDxF%6#fQ^w|Hu@1CdKFM9@{AR0P5=t6hD?c;4b@Eki4yVTYPb0sjmY!iOON1v? zxx($nZ#v1NEpsFY0@ylrgKzha53c~8FAJN@e4p!)6cw@0Q94~vF+&Aq`PbmneH)0f z&Onc*)I5E3<{x`7YLZ$74{Rcs)v|&(b3poaX6o;rvBvKi~O8crL z>v>++17maR-lDUT!s8j#1lG}q1DA06>_xU)+Uirm-q(9XLxP_jHBN zrGS83Y1gqe$=mKK>O?>-fFOPSlu&$!j1Z7hx!^1nzd(8&FN+9M6^pMF5-)ef>!KB$Apfr*`)9tOYyO4(=7!l~li(NuKrYfigco#0h zOC+W=0p{U7yvnK8Gpk7eo9Y+qX95Of(}5SeunzBQ`0}pt@P%P82@Uf>ts<#4`6tXw zDNR4WJWmIB{lAOfX0aX~`+KDotSkUrneG}cfh$p^vO0`S2D#5aZMJNxMaYN7*~^+# zkH?IR|Id%R0AwNUo$W1lL09nTodE&oYcT0Jm_$((ZP)G2n3^N~CF^ z?tmVnCH7&a69ep`6L`tXTL}EY2&g0*%_*JWt}DL){q+6RpRe5oSQz-)?YSQvsij!G z(VKz^Q!T)ps84}un1SspUAxQJp6Bq6KWgiI4D*QoR83iF@I|{f_d|=|3&*oUm6&y6 z^wA|n&9EAx*B@_^lIH|{OW2KL>$36H&rp^NHW0r^&p+N*?(T=FBuAQJHpD^OKp<~O zRZovt<)a62|Hub~f4<>a{5O0oeodEzfOwOXxSXGPX^|TGcMX?#kM7S%dm)D(>f8;K z(SV^4Aol4$Lg~7`c!&;JcB3+MDOiQif{LtS+$cYeTAt3h{dwA-6NA)c)B<4z4ScKH zyTx;f8lM5Ea@lQu9Ch05UD`MJr++HGs7mj>N&cUw__?EVjdb_W$mx!M)Ecj^DQtuU zP(DVL`frY!gXPu0WJHSqNVBE`E@CdT(5mZ}{n+*NW-Qw2^XP{}?nZ$b%UC?H89r;0O3>T0*ds=Buxj9uCsu5$p`nQv=8-|Nl#vVO>E;3LJ=UKZn!O= zfN~+3(*xLz`L8>#DmOnOkyT{!mb)l;oV$+fH2v;$1^^Ad((AGSfSHfnyU2=H(~w6n zFeg8n`dk8da2?e1y~VkDP^;(VRvy>#61HsTM&>9wrcyg%z@cXMdR0HJnt0!+8k$5{ z))mN67W*G|?lPg**o4KUxaw9@tQ()n<-Zs`T1S>2jpxDaU*aPGjS^2%0?b)c1Fp_ppZLaYFCR`J5<)$4ts7CdH z@l`tjY|?pSCrJ@Z4ulYDqgp@>;p!@)7Xz-Y6bn93@-p|?S>1&_k0>4I=45AO+08Mq zN+BG}CSZWu0Truob3*YOJO~puF@_To?8$@(k}+N9@)?l5=7G$vW`?OyBy!a}0|Jip z#7h7=-pak`Po|?M%d`f%F2*Jx zRuW=9U*ltyY^S)pJuI>-=NWky35wZ6{_T1NXgb)iaUxM|)*eE7-Mik%l;vqp84NWW z8yDpRH9oBXn%<*5q0HVI3Q#>i#S5OB_X|H&!=c1j+;!=0wX{g|Ra&}<0m!H{fN-s$ z+xqA$y$gUgaJ4NcrVDm^$ z4&3EuJL)mS&=-w_+QxIxHzBRRfRUCBpm$7Sy&q->0({rmpaoc+dXPlsMIy!W7Q#mn z+p(wkx){s>{`NZa>>ofJ_B%ps^#VKy_=~G@R46<|W`$oLf5o6cP?nH^Ipe};e~jD$ z+ES#vsp;aG>EcDBSo<1M{DKRvKjta-@kJEd5Z5)(TP65FA-3$(!|(&-68%AS0*UZ?@`x zpMBpI9qifJz!PJ>P`ZEi^A7^!rvX5{2!C1PQW5H2_No{FZ)`kIA|PPcDQ^jnjZVPH zX%E}M_schLNz?+gIlp7%W8J_kR*4Z1{J*9BR^`!QuE86D?)_yhHi{2G3F>8uV{8FW zYd0}j{LLRsh!$y-iC>p`NKf+kUoDApj7`o!y1D(N9fJtQ_;h zXc>*h{#j+@0IcUjO2g3!T72b)wn3H8Mz6%-o+wA2Raf)Y5PJDdGP8=clhN+O+hw4n z4y1(d=@O}Xq#yNRX2D5e;FyJsKQZLcpS*3%zI~|_0O{A*<=Zp#EWu{3;6|MM8U05&C-go5Su2Y|;-*yD$;mQ!$P0+&i3*r&k{QQ8263eYOg`8$IaS+`; z96yCkgpuG#KyhilDK0PyoFWRqO7G5=r%5q@nY5N3;&MTuwr{%?$x-hrMi1wW10ZV_ zBwEjq9cQQ!0fa-E5GNqt9(+h5py*meLr8TJn)XDA~fe5LK z_XQ%%L038;jQ5QZe)Mz%5I)o19RZpE43WKKi+_d)QsD~h>_r!l_(EFlu=c6fCdau+ z?vyHXp?iQ(IG~FZE`>Cp?H&V4)XG&Mk)x@=2srZk+ir0w3@>wY%l=}&GtiZO zG2uR1@(?o?kSFW{MOm33nc~p8E8$xO?O=L~v@#fsq+fa$i=j^d5G$lG#wJvVE~sIp z`jlk|Be4L;DQ6bw9FBa0tTJq%yb~fS7j|FnA;cwEP3;I*1PPSD)EuUJ531WxI2z0i zc>9va8`2J%fU(bUbjiR|`2HW80RMmjAW7hx0DBQD6y^V)nlMxKmZ!h_Qv(Z&r8*pZ zH|cyz|CH&ZFv0c=pN!P$SlK&CFmtx(7P8hP4 zv4F=y@%wut??g5;5yDHJ!~(HW?En4_dj{@G7RQu=;>obH-dO<{Lc^Ha$KrcW=>_>y z+#DV@-tCTyaI&L%cqcXtjhH#&nxk|I<`7sEfGAI|_o4MDaQpo!PkUwyTgO72ivMoP zchPs~h*yQ+kBT!=suNCi`bO1&O$T^ch)L~W3n_+6{k>WD)&mTMi^A?`;JgMOvc^io z0^y3|d6Xd=qOlH1pC0fdxwd2ct2U1%xNhIK@YCb+RA$`-?4)1kz8u=UlmzJ@h3N$5 zpx_YDl<^=U=iYk|Ki<(3kieaN%;dT7@dB!>*uT{M2lOUMgNrqFLhVp*Yau@5LGD+7 z&M<%v0f7c>lor}+S0csX$`S^67dx3Z8 z!!JcqaP8dtV#J%$zHndoFBX7`3?4yQfW{whiG^RFkW!qQK3*x#4{6=GTgwOkO;LMa zgU2`4eld-@jSY@{BrZfM?*ATv2p-{x)X#(H5!m2xM5|({LjUi#;?UGm?;3)b?Xp&S z@>CIP1^?~~fao8Ld`JT=c@M*>lrz*R@g>}6cT$_fjm22-Kc0Xwc%Suee-fad_Tqo~ z_aFG5uE5k^kiuX8k4W)9e>zTQ$Uvxs_SfA;_OSoG(_yVD{y+Z)zpbhxe7F0Q@_!i_ z_$%OgV}d`||GO05_P^`@b1D8U|6RXEYv?T#t^9U3O9QV6mg+53WJUK<@QOyE@U28F z-0`ep^zk^kq33EWlq}G)_X7E#eD~8uzrgn#3G6b`6OmzL=&9ZS61ndENsWK_*c$LR zqxz&C_Z@u`Iv5uJIjKQUhoJ>BK8BM6-ZShpw4!_2p5@;MLx6{BYsM?+F@M4e$I3T@ zkmrAzeF4p4BYbO6v+Ibc?8T@|`0v^QxOUx!U=Gc0Vq`aANOAGr?v>E47_|G7AW8=< zm(qatC9#`UM&v5|OR);WwZ-?wc+n%9!3VzBqDuR(-MR>9x7`eH-9Ux->30hl6LuY` z;OcXyVDw&A%s?vw?F0Br0)b;{ySIhkeud6ZmY0&i`vjr;#N=}>|0}1dz)L9fJyt?5 zgn{9x-1y__=-)>sFo1`uczqr%0-Vgy?6A3|#Y1RicPzkc9PGlk!wG9&714iSH1N~z zVEXqTaC?{m=or5bpMrq@F#Y#6rT+cInhj&(zR14^ApZXxR%del`$lj*49nf?|6Pi2 z`#;0---yJ&#lP#TlJ<}v-S8V0`1?t)4=}F-V8_1N29NXK@c_O9q>Rv9S9eokgujO< z9He16e*Wnh_=FQM>MjoWsiJqRdk?*SN4yw~bNsVV$wObBDPS-`pD+i$Pneu8FOnO; z|Jo0zs;tK;Zhp_D^ zEt*DkmC)>V&x3>iu3bmgSI*>jz0kFW@W=#~R1g2dyO4%OZ1S==1h{RazzjoW9-5mLE{^*hKLPEb$$t<^fGzhk&1~5y1~1DTLvFhkRakrG);xkUwYEy%G6H zFd0FVF(Kf!>3|Or6L2~aU9$`N!2;3R+TH=tnF+a>fC$MOiMSL3pdm$|*mesCFIxGb zXGgW+2|b)x5nCCN8X!kKt9t>_k>_xbYwLt=wS<35cbshgSTFYb8WKD_of$0xHW{tq z>kvP4HNA(bQV2>^WB>_hrO$%GAMCqJs40O!6YBxVGf)ZB0d1?188AdFwFXK2r8yTny=!ZCNKPeP`p+WV4e4>(nDlhGKADo`vhC3mb6fm>sf{K6zq8&q8 zslI$vBTyHN1s$i=0n&345)hU7{PpK+!_}A!F%&2RglY)jMDVPA-Lr-egDLq8R#9fi zsR4MxU;3_2GnB25MLGdJx*KVmc}~S!f+P1Kg>B!3FpGCjwWf@;pEv6-D?a^vD()kLWBmcq8ABL!_kRw6x@`;6 zaV&liqg!k@Cx)RS;{$1U$j{mXo0J@YIbL>1cw{LPrzR8N&zDvTp1cT4u9}3X!({ zA;;LZY$mW~(;ml>k_$Y;YGmr$czDxXKVR*b=V<0Zbc8FbvGTXhNe`hW0l&_yK{$}( z-8cG9-q>30v6Vz}bZM1S_E4%lUx`kt5SdPVEddGXQm_J4>}W|Qib^w;y0lb6N_Je8 zJ~Q-!8*9-G6`0%cvTxDqMEeR}=Ow-qbl zHtDFH&W&l2)E%Ix9b4wJrq~;m_LQoBiOgRf^1X46^Zk8_H-Md?c3f8>A@pq|DlYe) zw?~m0s{ky8G3H!kXpRzVOUZnX3w+s;s`gD$^gJ@DiTtH&+mbXm4BS44-&40KDVA6J zoi1fcXTic`<7i_we!lJZbAJrn`w?!hg#K+@`b{nfW|o8XY^zUO&S>w~zAZg1Ck85b zPaO{noRF@TUOGVG?V0r``7Tf*TRT-zm1Y6f)WJ)^_V}&u8L8P>v2;bO44b#e2pQ?( zy-i3vq2yh$|2mRFvuuj>XI#l}B)2JFRu`6)5aK4;sPj=py%APlM_6ej?a*Tx;UjOx zS#`q@$y}d1#KvL}sxk+O`K-M$=h5O?0Xx)UA7L*GG)_`k1?8*08g~(aRWAUsxum~P z|1AmrK)PqZGjyNqS4b&V773EWxj74v4Ic!_RTn@ipfrUPl1@?cA}&VWbXKj$o-|Dh z8Q=OrC~4&FWFMq&D{XQ`z~opaCAshu6q%mEZ$y8Xy)X!y05&Iu zCjBEOALmox)apROL!7)LpZ0xf!7`Az((zfj)3HVd64yrtnfl^|>JR9YxUGeW^P>wS zz*^NPxQ_~!t^=0H2dDXdkA$l=)0Q*CWvrVps5U?nP?P??Ss>}`8rGls(AZsKq$8s_ zD~+UPyvyJ~@Uxth6Ybbkt_107*!rSG7PH7o)}shB$+SRk;NFA~lt60AnhvsbtAzB4 z?IAj|pt7;fCk%pI=PLDMd_>Bo#M}afKM%~K)ksfAl*vrzl44-v9EmHx*9YoLMS2I3 zCYi7?IC43ZBbqqRu|ra3Ju=oY$x_BZa%u-n26_%NQJHy7Fj?)f`2{)MvmxKjdJ57{ z5jP73MbuOCQ7Jc4d&mZ2xGL$aRR?2vSRH?WM^@1?8LfgD7s(~$vE|do`~n{@l)?n< z|5KcZp7al~g@P&rD?Jr)$!p+iUIgRjVd++iIJ|ro_yiJw`#c&?TEux5 zy*e`V`c5p->6EhgO)BL7j-FaK%E7+>hyu&rS*2N6$_)!pp?+;7@e|~34DvDX+6u?A3MesPpnRoE&Uq$TD>qRsS(z=Z5K@6$ zeDs%CkudRvxG{P3rOy*fY_HuG-CU?;_ZNqB`|Mbx?E&{8FWjtfA~SJCI43I{%yeLh z00rWwZMWdtg}-{l9>x!y_4bB6JNo2D2|-#oABq^lDo_>^Z)XNYLn(UwII@>~2Fw%Z zRL-M6;v_`Auu~IIM8)O_j7njx&^P)$(t;kMniN@&g9GG|lnxXMKyBI%J6-I#HlsDRK%eoQ=Cw*){f`Y&XuyH zCtil*hQ&8!UbuHG3`{B=|8s0qV$j)x`J^XMs&J9_jByf06Bhloa$QVfPtYa_%ESoOEjsd;|JX;6q?SQOc4Sw6K_guUX(9hx14@>VLymn+ z@)K#G?O02pvZ=Qe85%_*&UkgE$1iN50@n^=l^Q&%KxF>-*(NRL}|*T zA{|muQJu2XNC=}1Ba<~mi=~)~v6C5FrI9*Xg+Yv^u}k))g_PZx8a2^o%p_taHMZye zs7{^l^B+9Vw;$%^HS$^B_j|ps>%K0;&kZRiSAZp&oC_xpT0(Ta5*n%U`6-w{QK7Yq zvzPS2PMC_x1ql!>7&Q7zuH`F^Hva{R0*D9qN7&XB!zj@j)oyHGa($DN7h*TA4t7pV zIw&V>FW*|aZY>!);QgT{kdFEYeL5dflyk~O&}v>QC8PBZ!=OiXVlapqr9?(80@#7$ z+y;yLCMyFTg2oQF7PAewZmhoj8ri7;yk-op0l?{0e_^v$kJ#h2uP7Km{{U~}_mmP3 zBt6eRI{Kmc3t&;Vx&>{cn?Z3f2lRMIAD_3I=?V!wpfAJ-{x&i%FK5;#&|C3K?rcm1 z1*p~P;gncpyZ8m>3$Q!ueEF?>#-b{z6bKhaxdpz1cG_}{L!wmx;}n36=(YQ}4%F#- zD-^P1r^Mqhhk`#pvP#(%slVZvj#}HO-;*`hw}m72;&R$vE8G?$%*4;oul%<_XlIM< zUD77MmAdi9cJJfoN2`GkQ|q%Cyy3amIf%Cyfck^?M+X)viqP8N?nmGg8#*NBVlVB-i4P>}5f`XNP#^z!6%)fe_t2$}N_q`Km) zAL#b$NJl%~|f&&%Y)R+z}iB62z!7V+` zb)b>@31`E_KSu!MUkW8Ka_J~hqzI@s99|LS z?oQn9R)f^-d_9o677lbagy0miKvuh;Yp5Wq*va?Bv5YMaAws4XhP;%p4%0R^0*spy z$PloBjq*}ee3Kg9|Ee3?SilWe+`n~RkPXe%F!3$q1h5!OG)Td!N+1aCj0%~aO!yhM zqb(LD3h!}q0$vZ&;u*zfxH>tDLc!+KPuXT0x)HHM&b?EHWF^pN$VOyx=(?^=n-<7v zG}Vlv zKADsj|6B3`Vpr7haT)-e z1zegN88k(t)?H$cp~Ze=_LV@LM}-4szy?$pQPht^YUBHj7wom6IrDgG+y%r+aCfRn z2EppixMQRbm1Um-kEm6^PJwugZuS(9 zo!}YqJiolXr04ZIc$69>HK;yZ3cHR@`~(;rcf*QW#rW_l=dC=EY*=N?+Vt{BLo7Ak z6-qw*-nYNGJ`jal--@JbWK_(2SYy1*&3jMm@+Wq_Y0jI5d13zvbf#shC?{6(WU5}m zNwVQ9Ct@^7fr`c_#A_KVatw1zb{xH1=pir=^p(W$((`NOuf}nozDaaS-@Byro&ks# zyh-Ab2%092S|cnC$&$Y_c0X)Mydbz^>bb~Te#-xqs>mBf3H2FJikKG|7!Db8?>&tL2KYg zKc)U@^0{&)utyS>`7MKKr~bJ|{BoFJ8`JbtYil=L`Cyilmf^(lUa~@LjT)YA;7rD@ zTH zXJ&Y(MK|%i+nwuxpz{t}%RB1cr&*=W+I2({-L;OOViv7E=E&;m*Q8Iu!1hi|<~sAT zqp>IKXy(yPY0}BoD;X@BG#7R)2^}&bgsdVh0uGtOW^{;y!|p_Eq#QQ&0qUwr%|wvY zoIo7bJeQ{yl&lUkM6}c3@Lxd1Dh@|QZu8I+#}*{wsI%@P2|v)nBPm_EeMNzzx`gyW zb7EV2>P^Y*T}qZJU!nES-F1lLia1?!BKL3z5)N-+JuHUmS0kG za5_|I^BvP&(}XCsi0$u%v3*)0=jevq4QluXbE2`3 z4pZNnsmvoc&MUumCP#(x2P?74fifSP{~Y6GIMJ%E)-72DT6OAMF6a}TnC=!P=EM)o zx&tcK(O4XB#h<~$b)UcJL4@eIr8Rh&O5pTKhPeevk3Wui0bewUK9EwikPJCB4Z z>3t15gxmQynPdW1+@VAK_cUT>sqV8Wj|C3RBeZy2S0;!2{VCr+>59*t%@St<}hBV9R} z%N_PrVBI1pr4pIR?h+#Dfqp73#*I3M*f5W}-ohr;wOM{$-__<(rm8e!VG4SGimlK1 zH4@p7cr+T@m`%)1v$(STIDcrXf^4RP(A%)0-##zr zHoG~ZfF%mgd22=AQZHM{-F#!pXd64EXD!^?t%GqKuoJ!D4ceUn@=bZNJ6pXWNDC7j z3&~eg+Ya_T(em_UQ#(Tgy-`dfRF{Tpg@}B{?w;^Spg4(F-nEUhDjH4M0!fni*_SRM z0MVn3w9;geu}RG-dSK>}_pW@b9;^AFO`IFwDDR>u-Ao~kn}|-04&h&SuWG+Ih&S@P zFZPz ziDu$U9O*mnQ4iSan-f=-_-9aJxU`2A8Q2GbCvr>q?L8C5e!)ViYHWHzVsK(wOHAlG zbB*F1?57p?K5qYhE$^8IP51hbvq>`H3IqIU*c`R8SZlOv}M zn>)u-tU?x+NS#NSh=)s3G|%9)L_>FQrv~ugC$r9o**aHzwxo>UrANdiikRtNomQ1t zjW;IK)W3^DwF+vT+mf>DHv&P|xpY&>j9A+$n)5@^nmvj8N!1f8oaaj+^nPuEoHWDf zc2%j6)8n(Co%P05&e(!&Z%ce$hMHS7TbQwVb>aSEUKQ&b^L385oX!%Xns+%XL~E>T z;vVZPCVfc@Ur3rI)NEK*2F=q_pWE<^T z<8a#_=Ft5Nhl)hgpK-EW)0EsSr^h5CV)!!REt8YRg2(nXy*VrXm@DmL$WMDfLr7qe zTG1=c>^>iRH`kKgNZB7PE@=kGB_(TXQxgl7b>+9)`(ik$*_GJJvw6}NrzR1Tl&O$P zhKkTHup+lzle6lAWg0EbwLxe|c9K7Fc>gsTLM;q+V)y`&kpxS!#Uy zxxa?Sv%oSme5!)hiVob_Vm@ouvg$oX1_WR-+t-oa!YOh1&`f&rC_z6_g%m7ou#els zSpcM#)d^#tJde>y@&YTPVygSqK61kqFkAZVJyCUef&s@+1m%;bW&p9D`H(X-fBz&vPua$D{ zGKeYVrdVJ1!KQk+R?X|`abbK|IiB&V!dIYi&Oc^VpfXP2aPE^^Q1T{qwc(!gLY)P5 z@*DG972Ds0IL>uaSVt9EsNiHpxgINPlH7@l4Dy28TQAnD0cs^7=iX=(lS$5~^&!&aSKGeZrRBK0zJ{aPr z-@bk80yD{@-6iMT1t~)ve=OY5OCd&Pi$YHj$QcHYrtT8(chs#)T4Hb;2gVl-;lF0a z9R?^U#s?V6T-OUtwB#`?rfI;ns5)F^yGX}lUuV9L0yTG)+HiZ@?JK~5{+T+PMfOJp z>ZCcXPn&kzS%h_VPKb&-X*|i*9^#<92BO3RW8SN;%@jvh8B6FMAwBMLw(3_eAH6=9 zuRq4B(k!+j)@xvFiSGp6R>VHc#XDR2Une9a^BO59qr|h12q=-FbdLP4kKck~ws=fR zlj4MHH{atp_T)@XtZ464o7i|N^Tdgx;VYmDe_55jbEW3I%EACv$JTeImcvbpDprOi zi?}Pq*WRj5b2av^CM_gYruuyV!A+yQqCRyO+X9zIyBAePO3RoUs(P+Bu?2f)GlNDW zo8CVDw>CfHX+m#5war4uy(OgW-X+s}wJF$u$GghmSOBX z$X2Em?GhEwl>?2!N{^Fw_JiYllqPd;G)~s&l380#XQsG=A^$0`#3u(H1R&)MjS;JW z7?11@bM$k&!MRpe!k|VXdz4GUcO*v9%&wKLH4wN^R{9jWOK^4!!hty6EunC~;W<{L zq_jqth+5o5VfCl;{{C~58ccF-4vWN_3-n5tg9|Wye*ZB$$h~x?9s;3$ zIN{p*w zDn?MzSBN0s4j8d&irppJTdBC-hw=rBs=|)AE6=H%rFhxW=VoP!@D`mB#C!2~MKVbv zH7|{{Dp*7Rd14*hfPtk7}9%CFV2UzCx+HV_Mi3-RIdTyrC;IYZ_tGLY16b**)Pc z(3Z}Lo@#+EvHoxEJ5CS$h21tio*vbexMN(rt1a=Zk5QgEtu@OqZ{4C>_7kNwlj>WR zIvTQMU}22CkCJUp&_k>zCaV}lGZQsZ zOIy37r6l)h7-4-Y%!XokjO~g~xvpE{Yr4J z^D6OIC}g_LFR>L+E^&%-2P8d~QuE_VGByt^U{vezj36`D!st)&M3cBX%af8^2d6HZ z+4OpT&KydjEK+aGG#)_opczpV6PA-Fz3}TRaV3s#>iQbWijtzzW0|E_vt`#ZFH8>1 zv3SB>p8#~i)&4q%Gff3A#ozA+mD>6Rx_r458KSn>(2L;eV8ZHZRj10fwbEgfWXQRdUka@Tfn0pjvL=I{tQvG6`B0>IsIOt$idWAM zer8(WO?KBv@ThmN^jksMW;wnV_=eqv)tV34e2FZJV*T6L&7vUnh;*mDRZJ1{3A3M6 zMSu-Kd7w`2qq54rdQPB(Ty8EuOZl$TA?BWoj{Ec#wlYoo{k|+!~bukXLE%w_AKq+ja{%~k}tiv-rQE(KKx1aYlz`#&|SeiVwvtsNAN#9C+WnahBJ|UPxnMDrl%W7(E-f1n=4A<3LtZnW{$6&X9 zmL6JpMj)%c|4Zc9Jyw@D{grOlwXA2lEVreRwsv(6CLfFBE1pL1vW(xkl(I*0`x-e? z_gx;WrtWRiKu5~U&0a**j_Alx^0(9wy!s+d%~tg+kJ6UI8MaP-qM(VWNDf8XA!qJAo;ZwzrL#2P2+CwEw>(y;61e}lnc=MpUzX&3kjvK^+S3DkOQa(5r3y!mo@zG&++l}2WPN9$QkFvDIL(PCqrf}GzuqWg zzM~!JD;PiPStKLjT8l)2dQ!Udjh(PYF2r(ajk0zeILLJbAVU7*kyg=P-ge8IR1F+7 zIdnD|OsM&p-noNAf|yF#Rh^X6>tnEvFwNx2zsci2_Wi=FYp;H7mv5Fl+H}V$iMics zF7_%zW^zX`$83@0fj5J}G_wTRubmWc5InyJ#f&$jcA3mwP{23!kJ0eZh`^#9-O^gK z(=uYiIY)z(rBii+LYqFStllFl>p#}+ohHhXNiF2z<=rJJlMMdI7IEoQBZ%^^!`ywZ*TQ@OB>^DYD;{8(TXqh8cMY43u@^n+-;v`r6Pg zE6R~l3=I_i*L8r<^kI3Mow!_J5F!BMT-r_?6%H}~>WoL}d4H0c6L~@GK&`xUAsoiz z>8@f~yIx33rLxr9GM5ed)+3o$5I~i1O0aN&MQs*&*=(F_#MtFw*?>*~YQb67=2HtA zx`SPa>SB{;7euorzCC9OAJ}{EU5O+60N7NJ6d`VKa!FH!{xBrzDXg{e2-jF&(HOQ} zm^zeydACB_#1}tK0R3TQFylQ<_y<7z=-LC8tHtU83Prd0rgcfYL)KN+o0s3$RR9Ua zm#e&|0G;m#kDRc8JRcyQqv*f)A!w<@JA|;V_vt0j8vbuw%wgCnfGWRCL3_|2K7?w<&x@>lMo;WFeTsQ@g4k zY`aE8yU?txY^EqxUrS6w+`w|tcZT~FDFmAZ&eiRShZ?Ow@|20aq=eoKw+Pdecr?TR z+-)9aEZyn-))GQ_2=&78CH@vvQwaB4^wa|kruy<;`f&t{vY6-AjAA%^FJX?eIgHqD zAfV^fbNPxnm4{Z4ZzCMVi?`%wf`8OrpD*h+i9(94W|0}<8bW0_#&-uZe zo?>^)*rAp|Ywgm((;{q&m{}EJ%7jK77jq&WX{EUJjsG2_~{WslM ziFe3kkt}*CPkx5*2U@Odn0ft~Go&J30E5JMT4EMn5q=Qwh$H+GYDMr%z$8hgj9SnRxu7)rRRSB2ZiVd<=@b1vn1zH{+zf-w+vg zieX{k^Hp0Ertb_lz~FQaNFgym#yfnVkn)6c$7x_#_@88IZ;w1foIVYdyFU?sXz)G)>hLZE#jVGs zHO?$?-#^4`d+)!EErQ`<2VnC@U>i!Fu~;V$hFb`~qWzzzMnZg1^3a(lYrb?@nwOnG zkb`bu0A6%Vjscwa3le4GGlgHTiB?@dn_=Hp9TGGS<#P-uE%EX(fNF}Erm&_}XkTd3 z{8GjD2zBJg-zbKmlucrbp{!`*fh`ONq=vd|I1Iu?fgXXL&`OQ??Xe>c&|uT^1@ddx zRf8aTcIa>$!(KZ>C8F@)I-dfh)%WeQH2-;NxXFm(=3`BmPPsV%X>K?@7OSAc2JT#3 z^y1SXM)5Do*N?}c?ML0ZMk|>Qygj-Y@M2GoIExh`-eM#duV1bF{U`nV5P*87WBfnD z)<4>fd>1;$(Zn0_zjqEKI_Qni0H;cprvFp8fiy5i94W&^N_GKYYlk$xj(xdL)+A8Q zy30u?Ho#P;4vO$d(@6oF3B#z#5cSX3m!mANsvm+@Qc>-R1sgBrg*h*u-_&b|Zb z*V%wA9|wG=1nfm@0LvOg0A!GwWdlFM74mbsUJ{CjkHZ#d&TkFf)c-|xT|NI^k1FJ>-_vZMsV}6bXQ?2w z%ghw><6|cbyx?7@|6#QM{N*D!b>h|3O?7AH-QS*f7&=R@%!SV1zM6R%RaxkfF7EC; z#3beSdxV(-Q|!N?_!;y6hT>;S{C8CRcU1iB3;%yd#q`3@w4y^s$G07y1^@OKn;GTq HI!yT=t%cH? literal 23635 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�+jM9sc;v1InI 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 IfA!D*0MQkDKL7v# diff --git a/bsp/gd32/docs/figures/scons_mdk5.png b/bsp/gd32/docs/figures/scons_mdk5.png index 556e677c51c58f9b8248fed0e179c27a08acf793..e62758136411ef7c679664bb8900e0346232586c 100644 GIT binary patch literal 19725 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 Q_s#gM%0UFjVZsiAig0w^LX3QF$*A+!*R5ITuU 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 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 10:00:27 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32105r-start/SConscript b/bsp/gd32/gd32105r-start/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32105r-start/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32105r-start/SConstruct b/bsp/gd32/gd32105r-start/SConstruct new file mode 100644 index 0000000000..49074397d0 --- /dev/null +++ b/bsp/gd32/gd32105r-start/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F10x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32105r-start/applications/SConscript b/bsp/gd32/gd32105r-start/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32105r-start/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32105r-start/applications/main.c b/bsp/gd32/gd32105r-start/applications/main.c new file mode 100644 index 0000000000..32fd8231da --- /dev/null +++ b/bsp/gd32/gd32105r-start/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + //set LED2 pin mode to output + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32105r-start/board/Kconfig b/bsp/gd32/gd32105r-start/board/Kconfig new file mode 100644 index 0000000000..deda10f857 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/Kconfig @@ -0,0 +1,126 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F10x + bool + default y + +config SOC_GD32105R + bool + select SOC_SERIES_GD32F10x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_ADC + bool "Enable ADC" + default n + select RT_USING_ADC + if BSP_USING_ADC + config BSP_USING_ADC0 + bool "using adc0" + default n + config BSP_USING_ADC1 + bool "using adc1" + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI0 + bool "Enable SPI0 BUS" + default n + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + config BSP_USING_SPI2 + bool "Enable SPI2 BUS" + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + + menuconfig BSP_USING_TIM + bool "Enable timer" + default n + select RT_USING_HWTIMER + if BSP_USING_TIM + config BSP_USING_TIM10 + bool "Enable TIM10" + default n + + config BSP_USING_TIM11 + bool "Enable TIM11" + default n + + config BSP_USING_TIM12 + bool "Enable TIM12" + default n + + config BSP_USING_TIM13 + bool "Enable TIM13" + default n + endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer" + select RT_USING_WDT + default n + + config BSP_USING_RTC + bool "using internal rtc" + default n + select RT_USING_RTC + + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32105r-start/board/SConscript b/bsp/gd32/gd32105r-start/board/SConscript new file mode 100644 index 0000000000..c1f4a6001b --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s'] + +CPPDEFINES = ['GD32F10X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32105r-start/board/board.c b/bsp/gd32/gd32105r-start/board/board.c new file mode 100644 index 0000000000..4a7c61b8cf --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32105r-start/board/board.h b/bsp/gd32/gd32105r-start/board/board.h new file mode 100644 index 0000000000..eb89837241 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/board.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f10x.h" +#include "drv_usart.h" +#include "drv_gpio.h" +#include "gd32f10x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-96> +// Default: 96 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 96 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h b/bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h new file mode 100644 index 0000000000..5292c8eca7 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h @@ -0,0 +1,64 @@ +/*! + \file gd32f10x_libopt.h + \brief library optional for gd32f10x + + \version 2014-12-26, V1.0.0, demo for GD32F10x + \version 2017-06-30, V2.0.0, demo for GD32F10x + \version 2021-04-30, V2.1.0, demo for GD32F10x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_LIBOPT_H +#define GD32F10X_LIBOPT_H + +#include "gd32f10x_fmc.h" +#include "gd32f10x_pmu.h" +#include "gd32f10x_bkp.h" +#include "gd32f10x_rcu.h" +#include "gd32f10x_exti.h" +#include "gd32f10x_gpio.h" +#include "gd32f10x_crc.h" +#include "gd32f10x_dma.h" +#include "gd32f10x_dbg.h" +#include "gd32f10x_adc.h" +#include "gd32f10x_dac.h" +#include "gd32f10x_fwdgt.h" +#include "gd32f10x_wwdgt.h" +#include "gd32f10x_rtc.h" +#include "gd32f10x_timer.h" +#include "gd32f10x_usart.h" +#include "gd32f10x_i2c.h" +#include "gd32f10x_spi.h" +#include "gd32f10x_sdio.h" +#include "gd32f10x_exmc.h" +#include "gd32f10x_can.h" +#include "gd32f10x_enet.h" +#include "gd32f10x_misc.h" + +#endif /* GD32F10X_LIBOPT_H */ diff --git a/bsp/gd32/gd32105r-start/board/linker_scripts/link.icf b/bsp/gd32/gd32105r-start/board/linker_scripts/link.icf new file mode 100644 index 0000000000..283881a728 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32105r-start/board/linker_scripts/link.ld b/bsp/gd32/gd32105r-start/board/linker_scripts/link.ld new file mode 100644 index 0000000000..8ba4a0e9f2 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96k /* 96KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32105r-start/board/linker_scripts/link.sct b/bsp/gd32/gd32105r-start/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0529ba2b9c --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00018000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32105r-start/figures/board.jpg b/bsp/gd32/gd32105r-start/figures/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f892317dcd94d4c689b130e24e3f7986b3810e02 GIT binary patch literal 133999 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 z%0D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 z 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

|-J_F~BpAz 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 + + + 1.0 + +

### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 10800000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + + diff --git a/bsp/gd32/gd32105r-start/project.uvproj b/bsp/gd32/gd32105r-start/project.uvproj new file mode 100644 index 0000000000..f7f70b89ee --- /dev/null +++ b/bsp/gd32/gd32105r-start/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread_gd32f10x + 0x4 + ARM-ADS + 0 + + + GD32F105RC + GigaDevice + IRAM(0x20000000-0x200018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread-gd32f10x + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F105xx, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + Drivers + + + startup_gd32f10x.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + + +
diff --git a/bsp/gd32/gd32105r-start/project.uvprojx b/bsp/gd32/gd32105r-start/project.uvprojx new file mode 100644 index 0000000000..14ba7f7137 --- /dev/null +++ b/bsp/gd32/gd32105r-start/project.uvprojx @@ -0,0 +1,769 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F105RC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F105RC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F105RC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + i2c_core.c + 1 + ..\..\..\components\drivers\i2c\i2c_core.c + + + + + i2c_dev.c + 1 + ..\..\..\components\drivers\i2c\i2c_dev.c + + + + + i2c-bit-ops.c + 1 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + + + + + adc.c + 1 + ..\..\..\components\drivers\misc\adc.c + + + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + Drivers + + + startup_gd32f10x_cl.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_adc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + + + gd32f10x_i2c.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32105r-start/rtconfig.h b/bsp/gd32/gd32105r-start/rtconfig.h new file mode 100644 index 0000000000..7f89e63117 --- /dev/null +++ b/bsp/gd32/gd32105r-start/rtconfig.h @@ -0,0 +1,212 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40100 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS +#define RT_USING_PIN +#define RT_USING_ADC + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* POSIX (Portable Operating System Interface) layer */ + + +/* Interprocess Communication (IPC) */ + + +/* Socket is in the 'Network' category */ + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F10x +#define SOC_GD32105R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32105r-start/rtconfig.py b/bsp/gd32/gd32105r-start/rtconfig.py new file mode 100644 index 0000000000..1839e540bf --- /dev/null +++ b/bsp/gd32/gd32105r-start/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32105r-start/template.uvoptx b/bsp/gd32/gd32105r-start/template.uvoptx new file mode 100644 index 0000000000..c41712a0e7 --- /dev/null +++ b/bsp/gd32/gd32105r-start/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 10800000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32105r-start/template.uvproj b/bsp/gd32/gd32105r-start/template.uvproj new file mode 100644 index 0000000000..592ba32731 --- /dev/null +++ b/bsp/gd32/gd32105r-start/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F105RC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f10x_it.c + 1 + ..\gd32f10x_it.c + + + + + CMSIS + + + system_gd32f10x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + GD32F10x_Peripherals + + + gd32f10x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + gd32f10x_can.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_can.c + + + gd32f10x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_crc.c + + + gd32f10x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ctc.c + + + gd32f10x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dac.c + + + gd32f10x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dbg.c + + + gd32f10x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dci.c + + + gd32f10x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dma.c + + + gd32f10x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_enet.c + + + gd32f10x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exmc.c + + + gd32f10x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fmc.c + + + gd32f10x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fwdgt.c + + + gd32f10x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + gd32f10x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ipa.c + + + gd32f10x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_iref.c + + + gd32f10x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + gd32f10x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_pmu.c + + + gd32f10x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rtc.c + + + gd32f10x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_sdio.c + + + gd32f10x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + gd32f10x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_syscfg.c + + + gd32f10x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_timer.c + + + gd32f10x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_tli.c + + + gd32f10x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_trng.c + + + gd32f10x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + gd32f10x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_wwdgt.c + + + + + GD32F10x_START + + + gd32f105r_start.c + 1 + ..\..\..\Library\Utilities\gd32f105r_start.c + + + + + Startup + + + startup_gd32f10x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32105r-start/template.uvprojx b/bsp/gd32/gd32105r-start/template.uvprojx new file mode 100644 index 0000000000..fd731a72ca --- /dev/null +++ b/bsp/gd32/gd32105r-start/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F105RC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F105RC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F105RC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32205r-start/.config b/bsp/gd32/gd32205r-start/.config new file mode 100644 index 0000000000..4c0efca811 --- /dev/null +++ b/bsp/gd32/gd32205r-start/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS 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 +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 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_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_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_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# 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 + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F20x=y +CONFIG_SOC_GD32205R=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32205r-start/Kconfig b/bsp/gd32/gd32205r-start/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32205r-start/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32205r-start/README.md b/bsp/gd32/gd32205r-start/README.md new file mode 100644 index 0000000000..e46626765e --- /dev/null +++ b/bsp/gd32/gd32205r-start/README.md @@ -0,0 +1,101 @@ +# GD32205R-START开发板BSP说明 + +## 简介 + +GD32205R-START是-兆易创新推出的一款GD32F20X系列的评估板,最高主频高达120M,该开发板具有丰富的板载资源,可以充分发挥 GD32205R的芯片性能。 + + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32205R,主频 120MHz,256KB FLASH ,128KB RAM + +- 常用外设 + + - LED :2个,LED1 (电源指示灯),LED2(PC6) + - 按键:2个,K1(复位引脚),K2(用户按键,PA0) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + + + + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +| :----------- | :----------: | :------------------------------------ | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART3 | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 09:29:49 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32205r-start/SConscript b/bsp/gd32/gd32205r-start/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32205r-start/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32205r-start/SConstruct b/bsp/gd32/gd32205r-start/SConstruct new file mode 100644 index 0000000000..14ab8b82ea --- /dev/null +++ b/bsp/gd32/gd32205r-start/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F20x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32205r-start/applications/SConscript b/bsp/gd32/gd32205r-start/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32205r-start/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32205r-start/applications/main.c b/bsp/gd32/gd32205r-start/applications/main.c new file mode 100644 index 0000000000..fc35bb08e1 --- /dev/null +++ b/bsp/gd32/gd32205r-start/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32205r-start/board/Kconfig b/bsp/gd32/gd32205r-start/board/Kconfig new file mode 100644 index 0000000000..49e208681b --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F20x + bool + default y + +config SOC_GD32205R + bool + select SOC_SERIES_GD32F20x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32205r-start/board/SConscript b/bsp/gd32/gd32205r-start/board/SConscript new file mode 100644 index 0000000000..d1c8023578 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s'] + +CPPDEFINES = ['GD32F20X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32205r-start/board/board.c b/bsp/gd32/gd32205r-start/board/board.c new file mode 100644 index 0000000000..8331a86841 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32205r-start/board/board.h b/bsp/gd32/gd32205r-start/board/board.h new file mode 100644 index 0000000000..9c42e83ac1 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f20x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f20x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-128> +// Default: 128 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 128 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h b/bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h new file mode 100644 index 0000000000..bd38888220 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h @@ -0,0 +1,70 @@ +/*! + \file gd32f20x_libopt.h + \brief library optional for gd32f20x + + \version 2015-07-15, V1.0.0, demo for GD32F20x + \version 2017-06-05, V2.0.0, demo for GD32F20x + \version 2019-04-01, V2.1.0, demo for GD32F20x + \version 2020-09-30, V2.2.0, demo for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_LIBOPT_H +#define GD32F20X_LIBOPT_H + +#include "gd32f20x_adc.h" +#include "gd32f20x_bkp.h" +#include "gd32f20x_can.h" +#include "gd32f20x_crc.h" +#include "gd32f20x_cau.h" +#include "gd32f20x_dac.h" +#include "gd32f20x_dci.h" +#include "gd32f20x_dma.h" +#include "gd32f20x_enet.h" +#include "gd32f20x_exmc.h" +#include "gd32f20x_exti.h" +#include "gd32f20x_fmc.h" +#include "gd32f20x_gpio.h" +#include "gd32f20x_hau.h" +#include "gd32f20x_i2c.h" +#include "gd32f20x_fwdgt.h" +#include "gd32f20x_dbg.h" +#include "gd32f20x_misc.h" +#include "gd32f20x_pmu.h" +#include "gd32f20x_rcu.h" +#include "gd32f20x_trng.h" +#include "gd32f20x_rtc.h" +#include "gd32f20x_sdio.h" +#include "gd32f20x_spi.h" +#include "gd32f20x_timer.h" +#include "gd32f20x_tli.h" +#include "gd32f20x_usart.h" +#include "gd32f20x_wwdgt.h" + +#endif /* GD32F20X_LIBOPT_H */ diff --git a/bsp/gd32/gd32205r-start/board/linker_scripts/link.icf b/bsp/gd32/gd32205r-start/board/linker_scripts/link.icf new file mode 100644 index 0000000000..ac4747c3cb --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x2000; +define symbol __ICFEDIT_size_heap__ = 0x2000; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32205r-start/board/linker_scripts/link.ld b/bsp/gd32/gd32205r-start/board/linker_scripts/link.ld new file mode 100644 index 0000000000..dbb8d1bf13 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F4xx with GNU ld + * bernard.xiong 2009-10-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 128k /* 128KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32205r-start/board/linker_scripts/link.sct b/bsp/gd32/gd32205r-start/board/linker_scripts/link.sct new file mode 100644 index 0000000000..f314c4bd58 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00020000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32205r-start/figures/board.jpg b/bsp/gd32/gd32205r-start/figures/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cc15375497461c94ac1cb072f921bf634599d3de GIT binary patch literal 161049 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 literal 0 HcmV?d00001 diff --git a/bsp/gd32/gd32205r-start/project.uvoptx b/bsp/gd32/gd32205r-start/project.uvoptx new file mode 100644 index 0000000000..3511a69bb3 --- /dev/null +++ b/bsp/gd32/gd32205r-start/project.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32205r-start/project.uvproj b/bsp/gd32/gd32205r-start/project.uvproj new file mode 100644 index 0000000000..965219aac8 --- /dev/null +++ b/bsp/gd32/gd32205r-start/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + IRAM(0x20000000-0x020000) IROM(0x08000000-0x040000) CLOCK(12000000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F20x\startup_gd32f20x.s" ("GD32F20x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F20x_3MB -FS08000000 -FL0300000) + 0 + gd32f20x0.h + + + + + + + + + + SFD\GD\GD32F20x\GD32F20x.SFR + 0 + 0 + + + + GD\GD32F20x\ + GD\GD32F20x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + __CLK_TCK=RT_TICK_PER_SECOND, USE_STDPERIPH_DRIVER, __RTTHREAD__, GD32F20X_CL + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Include;..\libraries\GD32F20x_Firmware_Library\CMSIS;..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + Drivers + + + startup_gd32f20x_cl.s + 2 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\ARM\startup_gd32f20x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f20x.c + 1 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\system_gd32f20x.c + + + + + gd32f20x_exti.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_exti.c + + + + + gd32f20x_gpio.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_gpio.c + + + + + gd32f20x_misc.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_misc.c + + + + + gd32f20x_rcu.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_rcu.c + + + + + gd32f20x_usart.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_usart.c + + + + + + +
diff --git a/bsp/gd32/gd32205r-start/project.uvprojx b/bsp/gd32/gd32205r-start/project.uvprojx new file mode 100644 index 0000000000..7799e20a62 --- /dev/null +++ b/bsp/gd32/gd32205r-start/project.uvprojx @@ -0,0 +1,726 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + GigaDevice.GD32F20x_DFP.2.2.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x020000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + 0 + $$Device:GD32F205RC$Device\Include\gd32f20x.h + + + + + + + + + + $$Device:GD32F205RC$SVD\GD32F20x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + __CLK_TCK=RT_TICK_PER_SECOND, USE_STDPERIPH_DRIVER, __RTTHREAD__, GD32F20X_CL + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Include;..\libraries\GD32F20x_Firmware_Library\CMSIS;..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + Drivers + + + startup_gd32f20x_cl.s + 2 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\ARM\startup_gd32f20x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f20x.c + 1 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\system_gd32f20x.c + + + + + gd32f20x_exti.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_exti.c + + + + + gd32f20x_gpio.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_gpio.c + + + + + gd32f20x_misc.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_misc.c + + + + + gd32f20x_rcu.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_rcu.c + + + + + gd32f20x_usart.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_usart.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32205r-start/rtconfig.h b/bsp/gd32/gd32205r-start/rtconfig.h new file mode 100644 index 0000000000..f685958fd3 --- /dev/null +++ b/bsp/gd32/gd32205r-start/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F20x +#define SOC_GD32205R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32205r-start/rtconfig.py b/bsp/gd32/gd32205r-start/rtconfig.py new file mode 100644 index 0000000000..4285e6b03c --- /dev/null +++ b/bsp/gd32/gd32205r-start/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32205r-start/template.uvoptx b/bsp/gd32/gd32205r-start/template.uvoptx new file mode 100644 index 0000000000..3511a69bb3 --- /dev/null +++ b/bsp/gd32/gd32205r-start/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32205r-start/template.uvproj b/bsp/gd32/gd32205r-start/template.uvproj new file mode 100644 index 0000000000..344c060ada --- /dev/null +++ b/bsp/gd32/gd32205r-start/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + IRAM(0x20000000-0x020000) IROM(0x08000000-0x040000) CLOCK(12000000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F20x\startup_gd32f20x.s" ("GD32F20x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F20x_3MB -FS08000000 -FL0300000) + 0 + gd32f20x0.h + + + + + + + + + + SFD\GD\GD32F20x\GD32F20x.SFR + 0 + 0 + + + + GD\GD32F20x\ + GD\GD32F20x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F20x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f20x_it.c + 1 + ..\gd32f20x_it.c + + + + + CMSIS + + + system_gd32f20x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F20x\Source\system_gd32f20x.c + + + + + GD32F20x_Peripherals + + + gd32f20x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_adc.c + + + gd32f20x_can.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_can.c + + + gd32f20x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_crc.c + + + gd32f20x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_ctc.c + + + gd32f20x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dac.c + + + gd32f20x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dbg.c + + + gd32f20x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dci.c + + + gd32f20x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dma.c + + + gd32f20x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_enet.c + + + gd32f20x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_exmc.c + + + gd32f20x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_exti.c + + + gd32f20x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_fmc.c + + + gd32f20x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_fwdgt.c + + + gd32f20x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_gpio.c + + + gd32f20x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_i2c.c + + + gd32f20x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_ipa.c + + + gd32f20x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_iref.c + + + gd32f20x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_misc.c + + + gd32f20x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_pmu.c + + + gd32f20x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_rcu.c + + + gd32f20x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_rtc.c + + + gd32f20x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_sdio.c + + + gd32f20x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_spi.c + + + gd32f20x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_syscfg.c + + + gd32f20x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_timer.c + + + gd32f20x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_tli.c + + + gd32f20x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_trng.c + + + gd32f20x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_usart.c + + + gd32f20x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_wwdgt.c + + + + + GD32F20x_START + + + gd32f205r_start.c + 1 + ..\..\..\Library\Utilities\gd32f205r_start.c + + + + + Startup + + + startup_gd32f20x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F20x\Source\ARM\startup_gd32f20x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32205r-start/template.uvprojx b/bsp/gd32/gd32205r-start/template.uvprojx new file mode 100644 index 0000000000..1ba7a286ef --- /dev/null +++ b/bsp/gd32/gd32205r-start/template.uvprojx @@ -0,0 +1,417 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + GigaDevice.GD32F20x_DFP.2.2.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x020000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + 0 + $$Device:GD32F205RC$Device\Include\gd32f20x.h + + + + + + + + + + $$Device:GD32F205RC$SVD\GD32F20x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32305r-start/.config b/bsp/gd32/gd32305r-start/.config new file mode 100644 index 0000000000..c8f9feac51 --- /dev/null +++ b/bsp/gd32/gd32305r-start/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS 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 +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 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_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_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_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# 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 + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F30x=y +CONFIG_SOC_GD32305R=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32305r-start/Kconfig b/bsp/gd32/gd32305r-start/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32305r-start/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32305r-start/README.md b/bsp/gd32/gd32305r-start/README.md new file mode 100644 index 0000000000..715f407e0a --- /dev/null +++ b/bsp/gd32/gd32305r-start/README.md @@ -0,0 +1,88 @@ +# GD32305R-START开发板BSP说明 + +## 简介 + +GD3305R-START是-兆易创新推出的一款GD32F30X系列的评估板,最高主频高达120M,该开发板具有丰富的板载资源,可以充分发挥 GD3230R 的芯片性能。 + + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32305R,主频 120MHz,256KB FLASH ,96KB RAM + +- 常用外设 + + - LED :2个,LED1 (电源指示灯),LED2(PC6) + - 按键:2个,K1(复位引脚),K2(用户按键,PA0) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + + + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Jan 9 2021 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32305r-start/SConscript b/bsp/gd32/gd32305r-start/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32305r-start/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32305r-start/SConstruct b/bsp/gd32/gd32305r-start/SConstruct new file mode 100644 index 0000000000..f32e96f624 --- /dev/null +++ b/bsp/gd32/gd32305r-start/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F30x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32305r-start/applications/SConscript b/bsp/gd32/gd32305r-start/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32305r-start/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32305r-start/applications/main.c b/bsp/gd32/gd32305r-start/applications/main.c new file mode 100644 index 0000000000..fc35bb08e1 --- /dev/null +++ b/bsp/gd32/gd32305r-start/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32305r-start/board/Kconfig b/bsp/gd32/gd32305r-start/board/Kconfig new file mode 100644 index 0000000000..5ef7ae972d --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F30x + bool + default y + +config SOC_GD32305R + bool + select SOC_SERIES_GD32F30x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32305r-start/board/SConscript b/bsp/gd32/gd32305r-start/board/SConscript new file mode 100644 index 0000000000..ec6b7bf3c1 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s'] + +CPPDEFINES = ['GD32F30X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32305r-start/board/board.c b/bsp/gd32/gd32305r-start/board/board.c new file mode 100644 index 0000000000..4a7c61b8cf --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32305r-start/board/board.h b/bsp/gd32/gd32305r-start/board/board.h new file mode 100644 index 0000000000..7bc2c83c60 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f30x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f30x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-96> +// Default: 96 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 96 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h b/bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h new file mode 100644 index 0000000000..e026fd658a --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h @@ -0,0 +1,65 @@ +/*! + \file gd32f30x_libopt.h + \brief library optional for gd32f30x + + \version 2021-03-23, V2.0.0, demo for GD32F30x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_LIBOPT_H +#define GD32F30X_LIBOPT_H + +#include "gd32f30x_rcu.h" +#include "gd32f30x_adc.h" +#include "gd32f30x_can.h" +#include "gd32f30x_crc.h" +#include "gd32f30x_ctc.h" +#include "gd32f30x_dac.h" +#include "gd32f30x_dbg.h" +#include "gd32f30x_dma.h" +#include "gd32f30x_exti.h" +#include "gd32f30x_fmc.h" +#include "gd32f30x_fwdgt.h" +#include "gd32f30x_gpio.h" +#include "gd32f30x_i2c.h" +#include "gd32f30x_pmu.h" +#include "gd32f30x_bkp.h" +#include "gd32f30x_rtc.h" +#include "gd32f30x_sdio.h" +#include "gd32f30x_spi.h" +#include "gd32f30x_timer.h" +#include "gd32f30x_usart.h" +#include "gd32f30x_wwdgt.h" +#include "gd32f30x_misc.h" +#include "gd32f30x_exmc.h" +#ifdef GD32F30X_CL +#include "gd32f30x_enet.h" +#endif /* GD32F30X_CL */ + +#endif /* GD32F30X_LIBOPT_H */ diff --git a/bsp/gd32/gd32305r-start/board/linker_scripts/link.icf b/bsp/gd32/gd32305r-start/board/linker_scripts/link.icf new file mode 100644 index 0000000000..283881a728 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32305r-start/board/linker_scripts/link.ld b/bsp/gd32/gd32305r-start/board/linker_scripts/link.ld new file mode 100644 index 0000000000..8ba4a0e9f2 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96k /* 96KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32305r-start/board/linker_scripts/link.sct b/bsp/gd32/gd32305r-start/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0529ba2b9c --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00018000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32305r-start/figures/board.jpg b/bsp/gd32/gd32305r-start/figures/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38d61dadaec95abca57cb4765b449282c3f068ad GIT binary patch literal 130595 zcmb@t2UJr*v?v<7Ql*2GAfTW$>7A%Z6A?iv(jp*D1f)j@1f)q95Kt5lkRk|(5W0jO zq<19Lgx(X75J?Cx-h1D>Z@sntTJQh$=VWsBIcMg~?3vwW&pzkB&zAw0?&%xp1E{E| z01(OnI7b6S^&lRu0Dy@J;06EyxIlTv0idBkRFvaC(m94&(nwbq{LtJ~-{`&`r2qgx z&G+vS^(6qn%R9i&+~AIg^%EPB|0w=ne~!-nFaP)J{{yDH13&$rElkM#AJ6`8E-yZF z@pq;a#8PsAAEj|hho4bkF1P=LDYyZ+oc3@TR16~GD z%Jls!@BGs5A3RTiwY**g{%h-B`Zp%bF5VW8C}(R*76kYM%mD^~I~4f;*Yw}x=~D;* zs2u|UG;ja=p3?^apdkhT;6wfQJ@L-~09!NwP(Sk0(a-TeIzvnOr*@^x?qMka!14qD z;2Z@27;XP&NB_I-f6vAL1Fj;JI)W5DeJF<;;03@1AObJ~cmtdPvJ^-Ga1$U8P&uCi z=mMyzsQ&%_E78!={7dw-v@~=K^b8FD@`Z~`7cX33yuiS~$im3T#7s#H7g^a@m|6e9 z|6cO1`oCI~AM*u<3;#;|zf0%s0QL)1{nQ&YRH6WCb}AZns`G9DkTQRC6x#ns{{NMz zsA*{F=qX)dWTF&+U!ruMhK8EbSvp$E;8BH9o&#vv={T;)-=^m@b7T2A3d<-kD=;ZhMA|nqkAOGd6*CZsb-%wIkQB_md(7mgtZ(wM2@6lrmODoDiJ3n)A zb#wQ4?jH~s6byM45)~a28}}wYAwA<=W>)t54>^TJUy4gg%f6QXsI7z7H#9aicXoC6 z^dkFy^^Z?XPEF7Jo<*TCE30ek8=G6(xWl7A$M_S%-_w71Q2}WF6RrP++5dqTI|VOl z${f%#{KJciI+&7a*lFpm$kTJ&He+z~Zm4NBYR%$Vyg-?hF(@E#h)-2ABNw%Z6XD}sgd9o@#+1wroSh)4*gvWv_>OP8&TLP(4-zMV zUvDAAKmx-gdQYL)?Y9!Ke~2=yohAa0J}s~ZbCZ^{6MDS#H$R~hPb3n8Se=g}a-?2Q zZdh04yDl`12!R;Ewey_h;%2w~an@(S@2v8EiRqsM6darP#Bzc&R803DSe3P}kgoq$ zPrX&xy0&J$l=*Nm`r){2_%`{mwR)=l=TD4Bsq(O9L?)zx#09dNQbPPb2lOax&Yad~ zzpR}Vh_7p0Q}vrYD*@GYrgGH1J&4x$@Q@>7Ju~V9(AqT;Oh@j8(TZTt0llWogivykP-MTs3>T zZct?A;QcHqzZr2dME{t)9e#&0WTFX2PPmQz(wZCBgA0fQ{O5p(e?u^?sQ0SC{T$Gk zf6`Z`Y+^H~I|gUDgHiDeQ<=8?Whr@L_=`jFyV=4UJF58{Xu)7eCO2+r_xKz@M~{Ue zK@3p-59fedFD)}%j%K_}fH8m1WR83+L*uiiWd-hJ3)`1`Z}+NSISaoWL$-hx1kJzu z3uo&=t%#3d9go79$US7$Fg7GAtJ+z)b$a^bM8!raJ1E3?{z^KPQo_yRDeEM+7@f?6 zQ{kpk!pE-WpsytZKB1-C^)-t&cKQfuY+u0`vc{Z6$5IekJ_c3|A6tT_c8$!cOmv
8e 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

ke@X}?lz1F>b|Q4h*b zzFkBAY^wU_+X$`b?>jfN`3pB~gZ6|!6ziW>ttM-RZOui7v?^BhGPwKv?3WYZ-)u8N z%MO~&4Hc*=!jZTAC3QP5mI#9@8 zRft=?^_Xj|3OrrKbA24Cuv=bRZm+B2LJJw*bFAm_vE)7uhuIgrRyRhLKh<-1>C;MM zf2^3D4GuZF`A08PY{}Ct{{5UYF)JcmwO2(-2^~mqCyDD++WEfI7OzhY2)zDDw1C=Z z7?r(#(r0DxM$Vx2+QmjOU4!@O^SMtB?;G^z`TpL29jZ&rEFkd{-75eKO><`FJb1uV zr9XX&Xj*=pK2@Zh#aiN(5hHkS0}w^(5}h;@J*8X01fgdWp#`~`Wae}~e`HgX+hIsx zA&`=k6+nS-_7Ab^bWnYMMn5xu=!emEvuKi36PXfPL&`@$MG(q>8{9 zrwC%+GSA4`wsJ{Xw58jqH*0|6n-)axF%Ehe(>|BKf2x@ckO7fYY?Eu_@;1c zddrh(s0y0(TI{8klX7te*V1e5bv+@PRu!BHiGvsG+||Z+0%3JQve)KFgT#y5n(%3T zA3SRAJqi-0ilWZc8&1}*;KassmI8DQhw+pDC~g86WSz4p@{CXCjpFP$!A0JG(qpf4 zelaBGMrIxEIj%UzYW=UneHZL1a|1pC3_%0mRw=WRJe==pY;D@sl>M|G7Bt8j+Q<@{ z#+H6@NuwZc?WpBkb%NeA0Ir+_QS5@p)-@gQZYWT*YbyBjpkyFl8z$95nm%F?f{(q} z9|`JMy@hMb2coltNLFZvK0A7hKfkuF{&Fco|bxDm%@V&A%3P=)s@ z#3dgUQA4L#J$$~;haYbgT2w=A^5Qd9iw_pWA4$^Qd>fGUMEY(8^s(>AoLkH*u6>0k z7k%Y4*=Pyil6f81PhnQlF*lw`*`4g|`)v(*53GNv-%>rhl`H}H{zoMJ^F?;ZwhIk- zyGu`nsB#&{E9oYR>EEN;)R83<%7%b zWZoSlFZdNRFHxb(b({zoH_(!Yf5bki>OUNC3%Ac+r~RF)@WMn;>oyTM7}X*^sUim3 zCIr0J{0LR}l)o*5tt+^OSZ|ThAF=SH{ppi^hx}x(ww*>|{snA-{2No98-qtaz(W!x zD_Wm42gGKK6Tjb6649Bx=uNxgE997>s`NKk9?Tx9y#k_zs>yUz#^$m&*BxefjW(YL`!Co9m@X9QDolV8jvqLOER9^@HgfDhDOv`;|91) zE?GTi0R|ae;gzFd8n=HkR+n#E8CNT32UnA;zQI>l*R<{u9id^TjC|%j4Z+D7<#q4$ zWU{mc^Sednc?CLbZp>lqN$N=d5)%0LzHl;^r$?=|x!kIcaJd^=n)c;_ck&5ACBBuH z&NFL*pqnn&t3VcEZsviEt+KYm*XlY=+`FWelY zYf;7^3nIO}tQTXHtDn8EUyl=gqcz;G)mfbVT)%Ho%bu`NLa4E6ts6VZp+3eic6lWr zaoop%<3Lqi!T?`^n{C8<7IF1xyisV)1qTr@5k~ex;@DjI1#CG&hMjunOs)?XYi8N% z+K`Xsn{4jpwhi=z-2es^d0X(wO+~~~D?&6HCq>&OJ@d&*Ex%xFf44nMc;BUo#RR> z^xj1mf?gw-V1wy3nFXddQHpnD6qf<~TH<9Db?cm(3(F3`YX$X38*K(T4g6&|>Itcg zYIRytoN{+NfmX1+Z1z+!n>=`a7SNHr^;!r7hNPLN=ogEj{LoQz>F5%uX9~CT(|Ch>ldh`4pmvc8$@hsG(FEk*@lZC$O zLD$uxp$CIJf3r_Hh?V&H&gLM16sqp&z5-}Xm!aOvbTRWBOKX%GW!T=G)Q0u6ADm)M z!?GHVy*$Vs%)2b=sgbG+0NrTa_~Jrs0d8%EJbpw68De?gan2I7?aFu!0)O76qB~(R zelmFBav=Jn(L~yX5pdG_yYu;m9sBAIitT?*DBb1jhi{K4*bLR$HgMfHFpM zLH8*&)#q2oUzisue03;GzJ9yEa*p-lca}ldW(2v}oxh8l6Tp2XPK1 z+{k-&_(dZXWh|??V{SY7D2pLeG~G|kTYt4z|D-&}@KMcp>TUy@!TQ1txm2fHt5xR+ z+pVm=sB+J`7Zcbl+)Frj!NWf{Dwf}SPp+^5c5#Zu5;+uDq-F({E0}{LWDUyIb zedp5b*@dAp!EFi4M$fXq#-u5|40FB#r4!=mavwsJIC$Yt%i>@aR;go}+v+6GiMcFF{%*5c;uIcmR>6wQI#!$;luGrOu z>o20XNk$>3nHQ$;K{A6LUa0Q_alSJc6m!hXu!TZ~1QvDvURYYliKDv9l{Dl#LeF(p zIaswIksQ?O{k{ezkAQ-n#SF_H|Mk%{`GRy9w(i8#SN0%p!u>T208|1vT8poyrWHew z>U=;=N_-ky{#@XbxSe5e^4Dg_A5NTc%!M4X<9@3lD6afO0w|kFPMx^lAlVnse>#q{ zRGd%@e_SjTJJw6Q0OAk;yH|M)j#@#Z0F7zoN_`3bphpJx$7pP6K5+(oWxHv z&5#%YLP3N4Ft)TMhNf@GVLfGJ71Ydh)*!vRfw5HK4Ks9$LYV4Wc<1JTt^PrP7&F3~ z7=3uui2xBY`aD^Q6DtSd{`yKrlpUjabMrQwbz#$THp|5aBGK2RIVtLU25@C02jEi} z5*yK+(9&Z^i%G>PH{nn;PZG*IuoyZ!*D*^2LC+U5tnaTgYoAX?f>;5N{Ci1+0Aj=( z17P3q5FDcT!W`Bvk&Y$#N`E>_Z}^?_Xkatvc|gD4ky8iHt;%2A4^w<0WvA_Y4dZ^p zG}HQfqyuJa9V(F1FKxC0LD4&y#oH`b_TmX9k>L7@I)cYcN4wCNUrV_J_8_s62O#nC zLWMBR6zwnbz=}Rh1vfo{w(L9sRdR=y7A3J5=K+YbgmBRb-(Xfh#>$GOLwN%oU1q2= zA7*}bzg2Rk;eCJXWcK})K6butXb?NWPGOT15OihHAI zkAgU5%AQ0snZ(Y*mhm4D{LKs5mpp(Swn1NjEYN|GRkm2DluS2S~Lg0NlRdAU!9 zm0oMTsp*dil{1_ey7k5zV&H_4L#{OO3jj+dc}(jjp|~SQ9e0{>VPN%l5awAygz2O{ z9rLJ-33v_*eE(FwVMsZmD{;&lm;{PoLiF;>UM7K|Cahaz*|Fp0=-?W-$Nl!34KwY_ z-evb^)WN$ZZYnb!|Y!>%a;s353UJ=oE%;#4q8oXPS&_0j?Utjci(yB@1lKd^XC!K5ii7Q$_AW{a*2(Gd)ulDx`rfOz^ghLq z|HNU`z+G_SLYm7=v!6avIzZYNRTMH)NK*YlG%tq>f&dv%r;o*ULogunA8ObWPQUV& zk?!3UGhvUiAdRQ787&g|;Y4N}kZ^2+Ii!vuEUso`wuWhyuAuMgRLS>#;e|EBH7;@` zhT262i~b^OMS9RtC-!0Ph0Brwf$7EBKdUQl-3oMb1X*o@T}GqX;GDSRlCMC_uysCZ z6*_v=l|yR7YMV}LH~!DRXyz4|`6-Op<&O=LI+kFMs?3EPGk#z&^oGg3`Iq0{cW>>q z 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 S`^}Zr7iR!7scikf)Bgjskk+pN literal 0 HcmV?d00001 diff --git a/bsp/gd32/gd32305r-start/project.uvoptx b/bsp/gd32/gd32305r-start/project.uvoptx new file mode 100644 index 0000000000..18fdad5165 --- /dev/null +++ b/bsp/gd32/gd32305r-start/project.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +

### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 0 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + + diff --git a/bsp/gd32/gd32305r-start/project.uvproj b/bsp/gd32/gd32305r-start/project.uvproj new file mode 100644 index 0000000000..34b3cd3d78 --- /dev/null +++ b/bsp/gd32/gd32305r-start/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F305RC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F30x\startup_gd32f30x.s" ("GD32F30x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F30x_3MB -FS08000000 -FL0300000) + 0 + gd32f30x0.h + + + + + + + + + + SFD\GD\GD32F30x\GD32F30x.SFR + 0 + 0 + + + + GD\GD32F30x\ + GD\GD32F30x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F30X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + Drivers + + + startup_gd32f30x_cl.s + 2 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f30x.c + 1 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + gd32f30x_rcu.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + + + gd32f30x_usart.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + + + gd32f30x_exti.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + + + gd32f30x_gpio.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + + + gd32f30x_misc.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + + + + +
diff --git a/bsp/gd32/gd32305r-start/project.uvprojx b/bsp/gd32/gd32305r-start/project.uvprojx new file mode 100644 index 0000000000..865d1a16b2 --- /dev/null +++ b/bsp/gd32/gd32305r-start/project.uvprojx @@ -0,0 +1,727 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F305RC + GigaDevice + GigaDevice.GD32F30x_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x018000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + 0 + $$Device:GD32F305RC$Device\Include\gd32f30x.h + + + + + + + + + + $$Device:GD32F305RC$SVD\GD32F30x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F30X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + Drivers + + + startup_gd32f30x_cl.s + 2 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f30x.c + 1 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + gd32f30x_rcu.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + + + gd32f30x_usart.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + + + gd32f30x_exti.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + + + gd32f30x_gpio.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + + + gd32f30x_misc.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32305r-start/rtconfig.h b/bsp/gd32/gd32305r-start/rtconfig.h new file mode 100644 index 0000000000..099327af24 --- /dev/null +++ b/bsp/gd32/gd32305r-start/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F30x +#define SOC_GD32305R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32305r-start/rtconfig.py b/bsp/gd32/gd32305r-start/rtconfig.py new file mode 100644 index 0000000000..a91905a233 --- /dev/null +++ b/bsp/gd32/gd32305r-start/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32305r-start/template.uvoptx b/bsp/gd32/gd32305r-start/template.uvoptx new file mode 100644 index 0000000000..18fdad5165 --- /dev/null +++ b/bsp/gd32/gd32305r-start/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 0 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32305r-start/template.uvproj b/bsp/gd32/gd32305r-start/template.uvproj new file mode 100644 index 0000000000..919038f7f4 --- /dev/null +++ b/bsp/gd32/gd32305r-start/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F305RC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F30x\startup_gd32f30x.s" ("GD32F30x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F30x_3MB -FS08000000 -FL0300000) + 0 + gd32f30x.h + + + + + + + + + + SFD\GD\GD32F30x\GD32F30x.SFR + 0 + 0 + + + + GD\GD32F30x\ + GD\GD32F30x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f30x_it.c + 1 + ..\gd32f30x_it.c + + + + + CMSIS + + + system_gd32f30x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + GD32F30x_Peripherals + + + gd32f30x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_adc.c + + + gd32f30x_can.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_can.c + + + gd32f30x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_crc.c + + + gd32f30x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_ctc.c + + + gd32f30x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dac.c + + + gd32f30x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dbg.c + + + gd32f30x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dci.c + + + gd32f30x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dma.c + + + gd32f30x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_enet.c + + + gd32f30x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_exmc.c + + + gd32f30x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + gd32f30x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_fmc.c + + + gd32f30x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_fwdgt.c + + + gd32f30x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + gd32f30x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_i2c.c + + + gd32f30x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_ipa.c + + + gd32f30x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_iref.c + + + gd32f30x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + gd32f30x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_pmu.c + + + gd32f30x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + gd32f30x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_rtc.c + + + gd32f30x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_sdio.c + + + gd32f30x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_spi.c + + + gd32f30x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_syscfg.c + + + gd32f30x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_timer.c + + + gd32f30x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_tli.c + + + gd32f30x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_trng.c + + + gd32f30x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + gd32f30x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_wwdgt.c + + + + + GD32F30x_START + + + gd32f305r_start.c + 1 + ..\..\..\Library\Utilities\gd32f305r_start.c + + + + + Startup + + + startup_gd32f30x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32305r-start/template.uvprojx b/bsp/gd32/gd32305r-start/template.uvprojx new file mode 100644 index 0000000000..0c172a57a8 --- /dev/null +++ b/bsp/gd32/gd32305r-start/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F305RC + GigaDevice + GigaDevice.GD32F30x_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x018000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + 0 + $$Device:GD32F305RC$Device\Include\gd32f30x.h + + + + + + + + + + $$Device:GD32F305RC$SVD\GD32F30x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32407v-start/.config b/bsp/gd32/gd32407v-start/.config index df22c29d4f..9b21611c11 100644 --- a/bsp/gd32/gd32407v-start/.config +++ b/bsp/gd32/gd32407v-start/.config @@ -1,9 +1,13 @@ -# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# # # RT-Thread Kernel # CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 @@ -26,8 +30,6 @@ CONFIG_IDLE_THREAD_STACK_SIZE=256 # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set # CONFIG_RT_USING_TINY_FFS is not set # CONFIG_RT_PRINTF_LONGLONG is not set -# end of kservice optimization - CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -50,7 +52,6 @@ CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MAILBOX=y CONFIG_RT_USING_MESSAGEQUEUE=y # CONFIG_RT_USING_SIGNALS is not set -# end of Inter-Thread communication # # Memory Management @@ -67,7 +68,6 @@ CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMTRACE is not set # CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y -# end of Memory Management # # Kernel Device Object @@ -78,15 +78,9 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" -# end of Kernel Device Object - CONFIG_RT_VER_NUM=0x40100 -# end of RT-Thread Kernel - -CONFIG_ARCH_ARM=y -CONFIG_RT_USING_CPU_FFS=y -CONFIG_ARCH_ARM_CORTEX_M=y -CONFIG_ARCH_ARM_CORTEX_M4=y +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set # # RT-Thread Components @@ -101,7 +95,6 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # C++ features # # CONFIG_RT_USING_CPLUSPLUS is not set -# end of C++ features # # Command shell @@ -121,13 +114,11 @@ CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set # CONFIG_FINSH_USING_AUTH is not set CONFIG_FINSH_ARG_MAX=10 -# end of Command shell # # Device virtual file system # # CONFIG_RT_USING_DFS is not set -# end of Device virtual file system # # Device Drivers @@ -144,7 +135,10 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set # CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set @@ -168,10 +162,9 @@ CONFIG_RT_USING_PIN=y # # Using USB # +# CONFIG_RT_USING_USB is not set # CONFIG_RT_USING_USB_HOST is not set # CONFIG_RT_USING_USB_DEVICE is not set -# end of Using USB -# end of Device Drivers # # POSIX layer and C standard library @@ -199,9 +192,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # Socket is in the 'Network' category # -# end of Interprocess Communication (IPC) -# end of POSIX (Portable Operating System Interface) layer -# end of POSIX layer and C standard library # # Network @@ -211,32 +201,26 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # Socket abstraction layer # # CONFIG_RT_USING_SAL is not set -# end of Socket abstraction layer # # Network interface device # # CONFIG_RT_USING_NETDEV is not set -# end of Network interface device # # light weight TCP/IP stack # # CONFIG_RT_USING_LWIP is not set -# end of light weight TCP/IP stack # # AT commands # # CONFIG_RT_USING_AT is not set -# end of AT commands -# end of Network # # VBUS(Virtual Software BUS) # # CONFIG_RT_USING_VBUS is not set -# end of VBUS(Virtual Software BUS) # # Utilities @@ -246,16 +230,11 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_RT_USING_UTEST is not set # CONFIG_RT_USING_VAR_EXPORT is not set # CONFIG_RT_USING_RT_LINK is not set -# end of Utilities - -# CONFIG_RT_USING_LWP is not set -# end of RT-Thread Components # # RT-Thread Utestcases # # CONFIG_RT_USING_UTESTCASES is not set -# end of RT-Thread Utestcases # # RT-Thread online packages @@ -290,17 +269,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # Marvell WiFi # # CONFIG_PKG_USING_WLANMARVELL is not set -# end of Marvell WiFi # # Wiced WiFi # # CONFIG_PKG_USING_WLAN_WICED is not set -# end of Wiced WiFi - # CONFIG_PKG_USING_RW007 is not set -# end of Wi-Fi - # CONFIG_PKG_USING_COAP is not set # CONFIG_PKG_USING_NOPOLL is not set # CONFIG_PKG_USING_NETUTILS is not set @@ -322,8 +296,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 -# end of IoT Cloud - # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set @@ -358,7 +330,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set # CONFIG_PKG_USING_SMALL_MODBUS is not set -# end of IoT - internet of things +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages @@ -368,7 +340,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set -# end of security packages # # language packages @@ -377,7 +348,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set # CONFIG_PKG_USING_PIKASCRIPT is not set -# end of language packages # # multimedia packages @@ -389,15 +359,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set # CONFIG_PKG_USING_LV_MUSIC_DEMO is not set -# end of LVGL: powerful and easy-to-use embedded GUI library # # u8g2: a monochrome graphic library # # CONFIG_PKG_USING_U8G2_OFFICIAL is not set # CONFIG_PKG_USING_U8G2 is not set -# end of u8g2: a monochrome graphic library - # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set @@ -417,8 +384,9 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # CONFIG_PKG_USING_PAINTERENGINE is not set # CONFIG_PKG_USING_PAINTERENGINE_AUX is not set -# end of PainterEngine: A cross-platform graphics application framework written in C language -# end of multimedia packages +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -462,7 +430,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SOLAR_TERMS is not set # CONFIG_PKG_USING_GAN_ZHI is not set # CONFIG_PKG_USING_FDT is not set -# end of tools packages # # system packages @@ -474,7 +441,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set -# end of enhanced kernel services + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -482,14 +454,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set -# end of acceleration: Assembly language or algorithmic acceleration packages # # CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # CONFIG_PKG_USING_CMSIS_5 is not set # CONFIG_PKG_USING_CMSIS_RTOS2 is not set -# end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # Micrium: Micrium software products porting for RT-Thread @@ -500,11 +470,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set -# end of Micrium: Micrium software products porting for RT-Thread - # CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set -# CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set # CONFIG_PKG_USING_PARTITION is not set @@ -532,11 +499,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set # CONFIG_PKG_USING_USB_STACK is not set -# end of system packages +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -613,7 +579,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set -# end of peripheral libraries and drivers # # AI packages @@ -627,7 +592,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set -# end of AI packages # # miscellaneous packages @@ -640,7 +604,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set # CONFIG_PKG_USING_NETWORK_SAMPLES is not set # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set -# end of samples: kernel and components samples # # entertainment: terminal games and other interesting software packages @@ -654,8 +617,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set -# end of entertainment: terminal games and other interesting software packages - +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set # CONFIG_PKG_USING_FASTLZ is not set @@ -677,23 +639,16 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_TERMBOX is not set -# end of miscellaneous packages -# end of RT-Thread online packages - -CONFIG_SOC_FAMILY_GD32=y -CONFIG_SOC_SERIES_GD32F4=y +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Hardware Drivers Config # +CONFIG_SOC_SERIES_GD32F4xx=y CONFIG_SOC_GD32407V=y # @@ -708,10 +663,10 @@ CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART1=y # CONFIG_BSP_UART1_RX_USING_DMA is not set # CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_I2C1 is not set -# end of On-chip Peripheral Drivers +CONFIG_BSP_USING_I2C1=y +CONFIG_BSP_I2C1_SCL_PIN=24 +CONFIG_BSP_I2C1_SDA_PIN=25 # # Board extended module Drivers # -# end of Hardware Drivers Config diff --git a/bsp/gd32/gd32407v-start/README.md b/bsp/gd32/gd32407v-start/README.md index 81cefde079..ec2604bf62 100644 --- a/bsp/gd32/gd32407v-start/README.md +++ b/bsp/gd32/gd32407v-start/README.md @@ -15,7 +15,7 @@ GD32407V-START是-兆易创新推出的一款GD32F4XX系列的评估板,最高 - 常用外设 - - LED :3个,LED1 (电源指示灯),LED2(PC6) + - LED :2个,LED1 (电源指示灯),LED2(PC6) - 按键:2个,K1(复位引脚),K2(用户按键,PA0) - 常用接口:USB 接口 diff --git a/bsp/gd32/gd32407v-start/SConstruct b/bsp/gd32/gd32407v-start/SConstruct index 48b90b094c..71deeebad1 100644 --- a/bsp/gd32/gd32407v-start/SConstruct +++ b/bsp/gd32/gd32407v-start/SConstruct @@ -20,14 +20,14 @@ TARGET = 'rtthread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, AR = rtconfig.AR, ARFLAGS = '-rc', CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) if rtconfig.PLATFORM == 'iar': - env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) env.Replace(ARFLAGS = ['']) env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') @@ -47,14 +47,14 @@ Export('SDK_LIB') # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) -gd32_library = 'GD32F4xx_HAL' +gd32_library = 'GD32F4xx_Firmware_Library' rtconfig.BSP_LIBRARY_TYPE = gd32_library # include libraries objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) # include drivers -objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript'))) +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) # make a building DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32407v-start/applications/main.c b/bsp/gd32/gd32407v-start/applications/main.c index 4a528128b4..fc35bb08e1 100644 --- a/bsp/gd32/gd32407v-start/applications/main.c +++ b/bsp/gd32/gd32407v-start/applications/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/gd32/gd32407v-start/board/Kconfig b/bsp/gd32/gd32407v-start/board/Kconfig index 190489eaa9..29331248c6 100644 --- a/bsp/gd32/gd32407v-start/board/Kconfig +++ b/bsp/gd32/gd32407v-start/board/Kconfig @@ -1,8 +1,12 @@ menu "Hardware Drivers Config" +config SOC_SERIES_GD32F4xx + bool + default y + config SOC_GD32407V bool - select SOC_SERIES_GD32F4 + select SOC_SERIES_GD32F4xx select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN default y @@ -70,7 +74,7 @@ menu "On-chip Peripheral Drivers" range 1 216 default 25 endif - source "../libraries/HAL_Drivers/Kconfig" + source "../libraries/gd32_drivers/Kconfig" endmenu diff --git a/bsp/gd32/gd32407v-start/board/SConscript b/bsp/gd32/gd32407v-start/board/SConscript index 95b376bd92..171600e2e1 100644 --- a/bsp/gd32/gd32407v-start/board/SConscript +++ b/bsp/gd32/gd32407v-start/board/SConscript @@ -16,13 +16,13 @@ path = [cwd] startup_path_prefix = SDK_LIB if rtconfig.CROSS_TOOL == 'gcc': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'keil': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'iar': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] -CPPDEFINES = ['GD32F407xx'] +CPPDEFINES = ['GD32F407'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group') diff --git a/bsp/gd32/gd32407v-start/board/board.c b/bsp/gd32/gd32407v-start/board/board.c index 0e9f89865a..8331a86841 100644 --- a/bsp/gd32/gd32407v-start/board/board.c +++ b/bsp/gd32/gd32407v-start/board/board.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/gd32/gd32407v-start/board/board.h b/bsp/gd32/gd32407v-start/board/board.h index b13b5439f6..237a77cc5b 100644 --- a/bsp/gd32/gd32407v-start/board/board.h +++ b/bsp/gd32/gd32407v-start/board/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/gd32/gd32407v-start/project.uvoptx b/bsp/gd32/gd32407v-start/project.uvoptx index 664bc65176..d7d2ffa02e 100644 --- a/bsp/gd32/gd32407v-start/project.uvoptx +++ b/bsp/gd32/gd32407v-start/project.uvoptx @@ -22,7 +22,7 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS @@ -117,20 +117,10 @@ BIN\CMSIS_AGDI.dll - - 0 - CMSIS_AGDI - -X"CMSIS-DAP" -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - - - 0 - JL2CM3 - -U59401765 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - 0 UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F4xx_3MB -FL0300000 -FS08000000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) @@ -179,6 +169,646 @@ + + Applications + 0 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c_core.c + i2c_core.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c_dev.c + i2c_dev.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + i2c-bit-ops.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + 3 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 19 + 2 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + startup_gd32f4xx.s + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + 4 + 23 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_soft_i2c.c + drv_soft_i2c.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 5 + 24 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 39 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 7 + 40 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 41 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c + gd32f4xx_i2c.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + gd32f4xx_syscfg.c + 0 + 0 + + + 8 + 43 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + gd32f4xx_exti.c + 0 + 0 + + + 8 + 44 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + gd32f4xx_gpio.c + 0 + 0 + + + 8 + 45 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + gd32f4xx_rcu.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + gd32f4xx_misc.c + 0 + 0 + + + 8 + 47 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + gd32f4xx_usart.c + 0 + 0 + + + 8 + 48 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + system_gd32f4xx.c + 0 + 0 + + + ::CMSIS 0 diff --git a/bsp/gd32/gd32407v-start/project.uvproj b/bsp/gd32/gd32407v-start/project.uvproj index e61bd5e518..876d693c33 100644 --- a/bsp/gd32/gd32407v-start/project.uvproj +++ b/bsp/gd32/gd32407v-start/project.uvproj @@ -4,7 +4,7 @@
### uVision Project, (C) Keil Software
- rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS 0 @@ -12,12 +12,12 @@ GD32F407VK GigaDevice - IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x08000000-0x082FFFFF) CLOCK(16000000) CPUTYPE("Cortex-M4") FPU2 + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) "Startup\GD\GD32F4xx\startup_gd32f4xx.s" ("GD32F4xx Startup Code") - UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000) + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - gd32f4xx0.h + gd32f4xx.h @@ -43,7 +43,7 @@ 1 .\output\ - rtthread-gd32f4xx + rtthread 1 0 1 @@ -370,9 +370,9 @@ 0 - GD32F407xx, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + GD32F30X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\HAL_Drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_HAL\CMSIS;..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel @@ -432,13 +432,6 @@ ..\..\..\libcpu\arm\common\backtrace.c - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - showmem.c @@ -448,9 +441,9 @@ - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c @@ -460,6 +453,13 @@ ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + +
DeviceDrivers @@ -479,16 +479,16 @@ - ringblk_buf.c + workqueue.c 1 - ..\..\..\components\drivers\src\ringblk_buf.c + ..\..\..\components\drivers\src\workqueue.c - ringbuffer.c + ringblk_buf.c 1 - ..\..\..\components\drivers\src\ringbuffer.c + ..\..\..\components\drivers\src\ringblk_buf.c @@ -500,16 +500,16 @@ - dataqueue.c + ringbuffer.c 1 - ..\..\..\components\drivers\src\dataqueue.c + ..\..\..\components\drivers\src\ringbuffer.c - pipe.c + dataqueue.c 1 - ..\..\..\components\drivers\src\pipe.c + ..\..\..\components\drivers\src\dataqueue.c @@ -521,9 +521,9 @@ - workqueue.c + pipe.c 1 - ..\..\..\components\drivers\src\workqueue.c + ..\..\..\components\drivers\src\pipe.c @@ -531,9 +531,9 @@ Drivers - startup_gd32f4xx.s + startup_gd32f30x_cl.s 2 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_cl.s @@ -547,14 +547,14 @@ drv_gpio.c 1 - ..\libraries\HAL_Drivers\drv_gpio.c + ..\libraries\gd32_drivers\drv_gpio.c drv_usart.c 1 - ..\libraries\HAL_Drivers\drv_usart.c + ..\libraries\gd32_drivers\drv_usart.c @@ -584,6 +584,27 @@ Kernel + + + device.c + 1 + ..\..\..\src\device.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + components.c @@ -593,9 +614,16 @@ - irq.c + mempool.c 1 - ..\..\..\src\irq.c + ..\..\..\src\mempool.c + + + + + timer.c + 1 + ..\..\..\src\timer.c @@ -605,20 +633,6 @@ ..\..\..\src\thread.c - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - device.c - 1 - ..\..\..\src\device.c - - object.c @@ -635,9 +649,16 @@ - timer.c + kservice.c 1 - ..\..\..\src\timer.c + ..\..\..\src\kservice.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c @@ -649,30 +670,9 @@ - scheduler.c + irq.c 1 - ..\..\..\src\scheduler.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - idle.c - 1 - ..\..\..\src\idle.c + ..\..\..\src\irq.c @@ -690,51 +690,44 @@ Libraries - gd32f4xx_syscfg.c + system_gd32f30x.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c - gd32f4xx_exti.c + gd32f30x_rcu.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c - gd32f4xx_gpio.c + gd32f30x_usart.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c - gd32f4xx_rcu.c + gd32f30x_exti.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c - gd32f4xx_misc.c + gd32f30x_gpio.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c - gd32f4xx_usart.c + gd32f30x_misc.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c - - - - - system_gd32f4xx.c - 1 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c diff --git a/bsp/gd32/gd32407v-start/project.uvprojx b/bsp/gd32/gd32407v-start/project.uvprojx index a41ce298ba..74a561886d 100644 --- a/bsp/gd32/gd32407v-start/project.uvprojx +++ b/bsp/gd32/gd32407v-start/project.uvprojx @@ -1,12 +1,16 @@ + 2.1 +
### uVision Project, (C) Keil Software
+ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC 0 @@ -14,29 +18,29 @@ GigaDevice GigaDevice.GD32F4xx_DFP.2.1.0 http://gd32mcu.com/data/documents/pack/ - IRAM(0x20000000,0x030000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x0300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) ELITTLE + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - $$Device:GD32F407VK$Device\Include\gd32f4xx.h - - - - - - - - - + $$Device:GD32F407VK$Device\F4XX\Include\gd32f4xx.h + + + + + + + + + $$Device:GD32F407VK$SVD\GD32F4xx.svd 0 0 - - - - - + + + + + 0 0 @@ -45,7 +49,7 @@ 1 .\build\ - rtthread-gd32f4xx + rtthread 1 0 0 @@ -58,8 +62,8 @@ 0 0 - - + + 0 0 0 @@ -68,8 +72,8 @@ 0 0 - - + + 0 0 0 @@ -79,14 +83,14 @@ 1 0 fromelf --bin !L --output rtthread.bin - + 0 0 0 0 0 - + 0 @@ -100,8 +104,8 @@ 0 0 3 - - + + 1 @@ -134,11 +138,11 @@ 1 BIN\UL2CM3.DLL - - - - - + + + + + 0 @@ -171,7 +175,7 @@ 0 0 "Cortex-M4" - + 0 0 0 @@ -242,7 +246,7 @@ 0 0x20000000 - 0x30000 + 0x20000 1 @@ -297,7 +301,7 @@ 0 0x20000000 - 0x30000 + 0x20000 0 @@ -305,11 +309,11 @@ 0x10000 - + 1 - 4 + 3 0 0 0 @@ -332,10 +336,10 @@ 0 0 - - GD32F407xx, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\HAL_Drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_HAL\CMSIS;..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + GD32F407, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_Firmware_Library\CMSIS;..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel @@ -350,10 +354,10 @@ 0 4 - - - - + + + + @@ -365,13 +369,13 @@ 0 0x08000000 0x20000000 - + .\gd32_rom.ld - - - - - + + + + + @@ -389,105 +393,96 @@ CPU + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + showmem.c 1 ..\..\..\libcpu\arm\common\showmem.c - - div0.c 1 ..\..\..\libcpu\arm\common\div0.c - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - cpuport.c 1 ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + DeviceDrivers + + i2c_core.c + 1 + ..\..\..\components\drivers\i2c\i2c_core.c + + + i2c_dev.c + 1 + ..\..\..\components\drivers\i2c\i2c_dev.c + + + i2c-bit-ops.c + 1 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + pin.c 1 ..\..\..\components\drivers\misc\pin.c - - serial.c 1 ..\..\..\components\drivers\serial\serial.c - - workqueue.c 1 ..\..\..\components\drivers\src\workqueue.c - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - completion.c 1 ..\..\..\components\drivers\src\completion.c - - + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + dataqueue.c 1 ..\..\..\components\drivers\src\dataqueue.c + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + @@ -496,28 +491,27 @@ startup_gd32f4xx.s 2 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s - - board.c 1 board\board.c - - drv_gpio.c 1 - ..\libraries\HAL_Drivers\drv_gpio.c + ..\libraries\gd32_drivers\drv_gpio.c - - drv_usart.c 1 - ..\libraries\HAL_Drivers\drv_usart.c + ..\libraries\gd32_drivers\drv_usart.c + + + drv_soft_i2c.c + 1 + ..\libraries\gd32_drivers\drv_soft_i2c.c @@ -529,15 +523,11 @@ 1 ..\..\..\components\finsh\shell.c - - msh.c 1 ..\..\..\components\finsh\msh.c - - cmd.c 1 @@ -549,94 +539,70 @@ Kernel - scheduler.c + components.c 1 - ..\..\..\src\scheduler.c + ..\..\..\src\components.c - - - - mem.c - 1 - ..\..\..\src\mem.c - - - thread.c 1 ..\..\..\src\thread.c - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - irq.c 1 ..\..\..\src\irq.c - - - components.c + device.c 1 - ..\..\..\src\components.c + ..\..\..\src\device.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + kservice.c + 1 + ..\..\..\src\kservice.c - - object.c 1 ..\..\..\src\object.c + + clock.c + 1 + ..\..\..\src\clock.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + @@ -652,82 +618,81 @@ Libraries + + gd32f4xx_i2c.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c + gd32f4xx_syscfg.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c - - gd32f4xx_exti.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c - - gd32f4xx_gpio.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c - - gd32f4xx_rcu.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c - - gd32f4xx_misc.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c - - gd32f4xx_usart.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c - - system_gd32f4xx.c 1 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + + ::CMSIS + + - + - - + + - + - + + <Project Info> - - - - - + + + + + 0 1 +
diff --git a/bsp/gd32/gd32407v-start/rtconfig.h b/bsp/gd32/gd32407v-start/rtconfig.h index dbaa1a76a2..529818a7ca 100644 --- a/bsp/gd32/gd32407v-start/rtconfig.h +++ b/bsp/gd32/gd32407v-start/rtconfig.h @@ -1,7 +1,8 @@ #ifndef RT_CONFIG_H__ #define RT_CONFIG_H__ -/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */ +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ /* RT-Thread Kernel */ @@ -18,7 +19,6 @@ /* kservice optimization */ -/* end of kservice optimization */ #define RT_DEBUG #define RT_DEBUG_COLOR @@ -29,7 +29,6 @@ #define RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE -/* end of Inter-Thread communication */ /* Memory Management */ @@ -37,7 +36,6 @@ #define RT_USING_SMALL_MEM #define RT_USING_SMALL_MEM_AS_HEAP #define RT_USING_HEAP -/* end of Memory Management */ /* Kernel Device Object */ @@ -45,13 +43,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart1" -/* end of Kernel Device Object */ #define RT_VER_NUM 0x40100 -/* end of RT-Thread Kernel */ -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M4 /* RT-Thread Components */ @@ -62,7 +54,6 @@ /* C++ features */ -/* end of C++ features */ /* Command shell */ @@ -79,11 +70,9 @@ #define MSH_USING_BUILT_IN_COMMANDS #define FINSH_USING_DESCRIPTION #define FINSH_ARG_MAX 10 -/* end of Command shell */ /* Device virtual file system */ -/* end of Device virtual file system */ /* Device Drivers */ @@ -95,12 +84,12 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS #define RT_USING_PIN /* Using USB */ -/* end of Using USB */ -/* end of Device Drivers */ /* POSIX layer and C standard library */ @@ -115,41 +104,28 @@ /* Socket is in the 'Network' category */ -/* end of Interprocess Communication (IPC) */ -/* end of POSIX (Portable Operating System Interface) layer */ -/* end of POSIX layer and C standard library */ - /* Network */ /* Socket abstraction layer */ -/* end of Socket abstraction layer */ /* Network interface device */ -/* end of Network interface device */ /* light weight TCP/IP stack */ -/* end of light weight TCP/IP stack */ /* AT commands */ -/* end of AT commands */ -/* end of Network */ /* VBUS(Virtual Software BUS) */ -/* end of VBUS(Virtual Software BUS) */ /* Utilities */ -/* end of Utilities */ -/* end of RT-Thread Components */ /* RT-Thread Utestcases */ -/* end of RT-Thread Utestcases */ /* RT-Thread online packages */ @@ -160,88 +136,67 @@ /* Marvell WiFi */ -/* end of Marvell WiFi */ /* Wiced WiFi */ -/* end of Wiced WiFi */ -/* end of Wi-Fi */ /* IoT Cloud */ -/* end of IoT Cloud */ -/* end of IoT - internet of things */ /* security packages */ -/* end of security packages */ /* language packages */ -/* end of language packages */ /* multimedia packages */ /* LVGL: powerful and easy-to-use embedded GUI library */ -/* end of LVGL: powerful and easy-to-use embedded GUI library */ /* u8g2: a monochrome graphic library */ -/* end of u8g2: a monochrome graphic library */ /* PainterEngine: A cross-platform graphics application framework written in C language */ -/* end of PainterEngine: A cross-platform graphics application framework written in C language */ -/* end of multimedia packages */ /* tools packages */ -/* end of tools packages */ /* system packages */ /* enhanced kernel services */ -/* end of enhanced kernel services */ + +/* POSIX extension functions */ + /* acceleration: Assembly language or algorithmic acceleration packages */ -/* end of acceleration: Assembly language or algorithmic acceleration packages */ /* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ -/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ /* Micrium: Micrium software products porting for RT-Thread */ -/* end of Micrium: Micrium software products porting for RT-Thread */ -/* end of system packages */ /* peripheral libraries and drivers */ -/* end of peripheral libraries and drivers */ /* AI packages */ -/* end of AI packages */ /* miscellaneous packages */ /* samples: kernel and components samples */ -/* end of samples: kernel and components samples */ /* entertainment: terminal games and other interesting software packages */ -/* end of entertainment: terminal games and other interesting software packages */ -/* end of miscellaneous packages */ -/* end of RT-Thread online packages */ -#define SOC_FAMILY_GD32 -#define SOC_SERIES_GD32F4 /* Hardware Drivers Config */ +#define SOC_SERIES_GD32F4xx #define SOC_GD32407V /* Onboard Peripheral Drivers */ @@ -251,10 +206,11 @@ #define BSP_USING_GPIO #define BSP_USING_UART #define BSP_USING_UART1 -/* end of On-chip Peripheral Drivers */ +#define BSP_USING_I2C1 +#define BSP_I2C1_SCL_PIN 24 +#define BSP_I2C1_SDA_PIN 25 /* Board extended module Drivers */ -/* end of Hardware Drivers Config */ #endif diff --git a/bsp/gd32/gd32407v-start/rtconfig.py b/bsp/gd32/gd32407v-start/rtconfig.py index 70651871c5..a91905a233 100644 --- a/bsp/gd32/gd32407v-start/rtconfig.py +++ b/bsp/gd32/gd32407v-start/rtconfig.py @@ -43,7 +43,7 @@ if PLATFORM == 'gcc': OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -DGD32F407' + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' CFLAGS = DEVICE + ' -Dgcc' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' diff --git a/bsp/gd32/gd32407v-start/template.uvoptx b/bsp/gd32/gd32407v-start/template.uvoptx index 664bc65176..6f7965ced8 100644 --- a/bsp/gd32/gd32407v-start/template.uvoptx +++ b/bsp/gd32/gd32407v-start/template.uvoptx @@ -22,7 +22,7 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS @@ -117,20 +117,10 @@ BIN\CMSIS_AGDI.dll - - 0 - CMSIS_AGDI - -X"CMSIS-DAP" -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - - - 0 - JL2CM3 - -U59401765 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - 0 UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F4xx_3MB -FL0300000 -FS08000000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) diff --git a/bsp/gd32/gd32407v-start/template.uvproj b/bsp/gd32/gd32407v-start/template.uvproj index 408784da46..69d95a4e29 100644 --- a/bsp/gd32/gd32407v-start/template.uvproj +++ b/bsp/gd32/gd32407v-start/template.uvproj @@ -7,7 +7,7 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS 0 @@ -15,12 +15,12 @@ GD32F407VK GigaDevice - IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x08000000-0x082FFFFF) CLOCK(16000000) CPUTYPE("Cortex-M4") FPU2 + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) "Startup\GD\GD32F4xx\startup_gd32f4xx.s" ("GD32F4xx Startup Code") - UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000) + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - gd32f4xx0.h + gd32f4xx.h @@ -46,7 +46,7 @@ 1 .\output\ - rtthread-gd32f4xx + rtthread 1 0 1 @@ -592,12 +592,12 @@ - GD32F4xx_EVAL + GD32F4xx_START - gd32f450z_eval.c + gd32f407r_start.c 1 - ..\..\..\Library\Utilities\gd32f450z_eval.c + ..\..\..\Library\Utilities\gd32f407r_start.c diff --git a/bsp/gd32/gd32407v-start/template.uvprojx b/bsp/gd32/gd32407v-start/template.uvprojx index e06b13d247..dd4e87c945 100644 --- a/bsp/gd32/gd32407v-start/template.uvprojx +++ b/bsp/gd32/gd32407v-start/template.uvprojx @@ -7,9 +7,10 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC 0 @@ -17,12 +18,12 @@ GigaDevice GigaDevice.GD32F4xx_DFP.2.1.0 http://gd32mcu.com/data/documents/pack/ - IRAM(0x20000000,0x030000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x0300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) ELITTLE UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - $$Device:GD32F407VK$Device\Include\gd32f4xx.h + $$Device:GD32F407VK$Device\F4XX\Include\gd32f4xx.h @@ -48,7 +49,7 @@ 1 .\build\ - rtthread-gd32f4xx + rtthread 1 0 0 @@ -245,7 +246,7 @@ 0 0x20000000 - 0x30000 + 0x20000 1 @@ -300,7 +301,7 @@ 0 0x20000000 - 0x30000 + 0x20000 0 @@ -312,7 +313,7 @@ 1 - 4 + 3 0 0 0 @@ -389,10 +390,10 @@ - - + + - + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h new file mode 100644 index 0000000000..41bae599cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h @@ -0,0 +1,380 @@ +/*! + \file gd32f10x.h + \brief general definitions for GD32F10x + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_H +#define GD32F10X_H + +#ifdef cplusplus + extern "C" { +#endif + +/* define GD32F10x */ +#if !defined (GD32F10X_MD) && !defined (GD32F10X_HD) && !defined (GD32F10X_XD) && !defined (GD32F10X_CL) + /* #define GD32F10X_MD */ /*!< GD32F10X_MD: GD32 Medium density devices */ + /* #define GD32F10X_HD */ /*!< GD32F10X_HD: GD32 High density Value Line devices */ + /* #define GD32F10X_XD */ /*!< GD32F10X_XD: GD32 Extra density devices */ + /* #define GD32F10X_CL */ /*!< GD32F10X_CL: GD32 Connectivity line devices */ +#endif /* define GD32F10x */ + +#if !defined (GD32F10X_MD) && !defined (GD32F10X_HD) && !defined (GD32F10X_XD) && !defined (GD32F10X_CL) + #error "Please select the target GD32F10x device in gd32f10x.h file" +#endif /* undefine GD32F10x tip */ + +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32F10X_CL +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#else +#define HXTAL_VALUE ((uint32_t)8000000) /* !< from 4M to 16M *!< value of the external oscillator in Hz*/ +#endif /* HXTAL_VALUE */ +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined (HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined (IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined (IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined (IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined (LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* GD32F10x firmware library version number V2.0 */ +#define __GD32F10x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __GD32F10x_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __GD32F10x_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __GD32F10x_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F10x_STDPERIPH_VERSION ((__GD32F10x_STDPERIPH_VERSION_MAIN << 24)\ + |(__GD32F10x_STDPERIPH_VERSION_SUB1 << 16)\ + |(__GD32F10x_STDPERIPH_VERSION_SUB2 << 8)\ + |(__GD32F10x_STDPERIPH_VERSION_RC)) + +/* configuration of the Cortex-M3 processor and core peripherals */ +#define __MPU_PRESENT 0 /*!< GD32F10x do not provide MPU */ +#define __NVIC_PRIO_BITS 4 /*!< GD32F10x uses 4 bits for the priority levels */ +#define __Vendor_SysTickConfig 0 /*!< set to 1 if different sysTick config is used */ +/* define interrupt number */ +typedef enum IRQn +{ + /* Cortex-M3 processor exceptions numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 system tick interrupt */ + + /* interruput numbers */ + WWDGT_IRQn = 0, /*!< window watchDog timer interrupt */ + LVD_IRQn = 1, /*!< LVD through EXTI line detect interrupt */ + TAMPER_IRQn = 2, /*!< tamper through EXTI line detect */ + RTC_IRQn = 3, /*!< RTC through EXTI line interrupt */ + FMC_IRQn = 4, /*!< FMC interrupt */ + RCU_CTC_IRQn = 5, /*!< RCU and CTC interrupt */ + EXTI0_IRQn = 6, /*!< EXTI line 0 interrupts */ + EXTI1_IRQn = 7, /*!< EXTI line 1 interrupts */ + EXTI2_IRQn = 8, /*!< EXTI line 2 interrupts */ + EXTI3_IRQn = 9, /*!< EXTI line 3 interrupts */ + EXTI4_IRQn = 10, /*!< EXTI line 4 interrupts */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel0 interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel1 interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel2 interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel3 interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel4 interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel5 interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel6 interrupt */ + ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 interrupt */ + +#ifdef GD32F10X_MD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD Wakeup interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ +#endif /* GD32F10X_MD */ + +#ifdef GD32F10X_HD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD Wakeup interrupt */ + TIMER7_BRK_IRQn = 43, /*!< TIMER7 break interrupts */ + TIMER7_UP_IRQn = 44, /*!< TIMER7 update interrupts */ + TIMER7_TRG_CMT_IRQn = 45, /*!< TIMER7 trigger and commutation interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupts */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global Interrupt */ +#endif /* GD32F10X_HD */ + +#ifdef GD32F10X_XD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupts */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupts */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupts */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupts */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupts */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global interrupt */ +#endif /* GD32F10X_XD */ + +#ifdef GD32F10X_CL + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_ALARM_IRQn = 41, /*!< RTC alarm interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeup interrupt */ + TIMER7_BRK_IRQn = 43, /*!< TIMER7 break interrupts */ + TIMER7_UP_IRQn = 44, /*!< TIMER7 update interrupts */ + TIMER7_TRG_CMT_IRQn = 45, /*!< TIMER7 trigger and commutation interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupts */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 global interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel3 global interrupt */ + ENET_IRQn = 61, /*!< ENET global interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET Wakeup interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ +#endif /* GD32F10X_CL */ + +} IRQn_Type; + +/* includes */ +#include "core_cm3.h" +#include "system_gd32f10x.h" +#include + +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +typedef enum {FALSE = 0, TRUE = !FALSE} bool; +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM0 base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB3_BUS_BASE ((uint32_t)0x60000000U) /*!< ahb3 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define USBD_BASE (APB1_BUS_BASE + 0x00005C00U) /*!< USBD base address */ +#define USBD_RAM_BASE (APB1_BUS_BASE + 0x00006000U) /*!< USBD RAM base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ + +/* advanced high performance bus 1 memory map */ +#define SDIO_BASE (AHB1_BUS_BASE + 0x00000000U) /*!< SDIO base address */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define ENET_BASE (AHB1_BUS_BASE + 0x00010000U) /*!< ENET base address */ +#define USBFS_BASE (AHB1_BUS_BASE + 0x0FFE8000U) /*!< USBFS base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32f10x_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef cplusplus +} +#endif +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h new file mode 100644 index 0000000000..6bd00fb99d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h @@ -0,0 +1,60 @@ +/*! + \file system_gd32f10x.h + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File for + GD32F10x Device Series +*/ + +/* + Copyright (c) 2012 ARM LIMITED + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32F10X_H +#define SYSTEM_GD32F10X_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit(void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32F10X_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s new file mode 100644 index 0000000000..a3ffa4c752 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s @@ -0,0 +1,390 @@ +;/*! +; \file startup_gd32f10x_cl.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; 58:USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; 64:EXMC + DCD 0 ; Reserved + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT CAN0_TX_IRQHandler [WEAK] + EXPORT CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBFS_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_IRQHandler [WEAK] + EXPORT TIMER7_UP_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT ENET_IRQHandler [WEAK] + EXPORT ENET_WKUP_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_EWMC_IRQHandler [WEAK] + EXPORT USBFS_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +CAN0_TX_IRQHandler +CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBFS_WKUP_IRQHandler +TIMER7_BRK_IRQHandler +TIMER7_UP_IRQHandler +TIMER7_TRG_CMT_IRQHandler +TIMER7_Channel_IRQHandler +EXMC_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +ENET_IRQHandler +ENET_WKUP_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_EWMC_IRQHandler +USBFS_IRQHandler + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s new file mode 100644 index 0000000000..fe768cc3a9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s @@ -0,0 +1,371 @@ +;/*! +; \file startup_gd32f10x_hd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_IRQHandler [WEAK] + EXPORT TIMER7_UP_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_IRQHandler +TIMER7_UP_IRQHandler +TIMER7_TRG_CMT_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s new file mode 100644 index 0000000000..c567fee5c1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s @@ -0,0 +1,328 @@ +;/*! +; \file startup_gd32f10x_md.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI Line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; 64:EXMC + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +EXMC_IRQHandler + + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s new file mode 100644 index 0000000000..3db249b8e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s @@ -0,0 +1,371 @@ +;/*! +; \file startup_gd32f10x_xd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 global + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s new file mode 100644 index 0000000000..e79129e8a4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s @@ -0,0 +1,273 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word 0 // 63:Reserved + .word EXMC_IRQHandler // 64:EXMC + .word 0 // 65:Reserved + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_IRQHandler // 75:DMA1 Channel3 + .word DMA1_Channel4_IRQHandler // 76:DMA1 Channel4 + .word ENET_IRQHandler // 77:Ethernet + .word ENET_WKUP_IRQHandler // 78:Ethernet Wakeup through EXTI Line + .word CAN1_TX_IRQHandler // 79:CAN1 TX + .word CAN1_RX0_IRQHandler // 80:CAN1 RX0 + .word CAN1_RX1_IRQHandler // 81:CAN1 RX1 + .word CAN1_EWMC_IRQHandler // 82:CAN1 EWMC + .word USBFS_IRQHandler // 83:USBFS + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_IRQHandler + IRQ DMA1_Channel4_IRQHandler + IRQ ENET_IRQHandler + IRQ ENET_WKUP_IRQHandler + IRQ CAN1_TX_IRQHandler + IRQ CAN1_RX0_IRQHandler + IRQ CAN1_RX1_IRQHandler + IRQ CAN1_EWMC_IRQHandler + IRQ USBFS_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s new file mode 100644 index 0000000000..023bfa9449 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s new file mode 100644 index 0000000000..71c3711013 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s @@ -0,0 +1,230 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI Line 10 to EXTI Line 15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm through EXTI Line + .word USBD_WKUP_IRQHandler // 58:USBD WakeUp from suspend through EXTI Line + .word 0 // 59:Reserved + .word 0 // 60:Reserved + .word 0 // 61:Reserved + .word 0 // 62:Reserved + .word 0 // 63:Reserved + .word EXMC_IRQHandler // 64:EXMC + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ EXMC_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s new file mode 100644 index 0000000000..023bfa9449 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s new file mode 100644 index 0000000000..76480fb238 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s @@ -0,0 +1,528 @@ +;/*! +; \file startup_gd32f10x_cl.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; Vector Number 35,CAN0 TX + DCD CAN0_RX0_IRQHandler ; Vector Number 36,CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; Vector Number 40,TIMER0 Break + DCD TIMER0_UP_IRQHandler ; Vector Number 41,TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; Vector Number 58,USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD 0 ; Reserved + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; Vector Number 75,DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; Vector Number 76,DMA1 Channel4 + DCD ENET_IRQHandler ; Vector Number 77,Ethernet + DCD ENET_WKUP_IRQHandler ; Vector Number 78,Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; Vector Number 79,CAN1 TX + DCD CAN1_RX0_IRQHandler ; Vector Number 80,CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; Vector Number 81,CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; Vector Number 82,CAN1 EWMC + DCD USBFS_IRQHandler ; Vector Number 83,USBFS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_TX_IRQHandler + B CAN0_TX_IRQHandler + + PUBWEAK CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX0_IRQHandler + B CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBFS_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_WKUP_IRQHandler + B USBFS_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_IRQHandler + B TIMER7_BRK_IRQHandler + + PUBWEAK TIMER7_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_IRQHandler + B TIMER7_UP_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_IRQHandler + B TIMER7_TRG_CMT_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK ENET_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_IRQHandler + B ENET_IRQHandler + + PUBWEAK ENET_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_WKUP_IRQHandler + B ENET_WKUP_IRQHandler + + PUBWEAK CAN1_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX0_IRQHandler + B CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_EWMC_IRQHandler + B CAN1_EWMC_IRQHandler + + PUBWEAK USBFS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_IRQHandler + B USBFS_IRQHandler + + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s new file mode 100644 index 0000000000..7f5356f0cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s @@ -0,0 +1,490 @@ +;/*! +; \file startup_gd32f10x_hd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; Vector Number 35,USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; Vector Number 36,USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; Vector Number 40,TIMER0 Break + DCD TIMER0_UP_IRQHandler ; Vector Number 41,TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; Vector Number 58,USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; Vector Number 63,ADC2 + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD SDIO_IRQHandler ; Vector Number 65,SDIO + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; Vector Number 75,DMA1 Channel4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_IRQHandler + B TIMER7_BRK_IRQHandler + + PUBWEAK TIMER7_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_IRQHandler + B TIMER7_UP_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_IRQHandler + B TIMER7_TRG_CMT_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s new file mode 100644 index 0000000000..6fefa84837 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s @@ -0,0 +1,399 @@ +;/*! +; \file startup_gd32f10x_md.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; Vector Number 35,USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; Vector Number 36,USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; Vector Number 40,TIMER0 Break + DCD TIMER0_UP_IRQHandler ; Vector Number 41,TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; Vector Number 58,USBD WakeUp from suspend through EXTI Line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; Vector Number 64,EXMC +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s new file mode 100644 index 0000000000..08659afcbf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s @@ -0,0 +1,490 @@ +;/*! +; \file startup_gd32f10x_xd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; Vector Number 35,USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; Vector Number 36,USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; Vector Number 40,TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; Vector Number 41,TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; Vector Number 58,USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt and TIMER13 global + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; Vector Number 63,ADC2 + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD SDIO_IRQHandler ; Vector Number 65,SDIO + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; Vector Number 75,DMA1 Channel4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c new file mode 100644 index 0000000000..5327aeb423 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c @@ -0,0 +1,1041 @@ +/*! + \file system_gd32f10x.c + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File for + GD32F10x Device Series +*/ + +/* + Copyright (c) 2012 ARM LIMITED + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#include "gd32f10x.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +#define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) + +/* use HXTAL (XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ +//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) +//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000) +//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) +#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U + +/* set the system clock frequency and declare the system clock configuration function */ +#ifdef __SYSTEM_CLOCK_48M_PLL_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); + +#elif defined (__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL; +static void system_clock_24m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL; +static void system_clock_36m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL; +static void system_clock_56m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; +static void system_clock_96m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#endif /* __SYSTEM_CLOCK_48M_PLL_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#ifdef __SYSTEM_CLOCK_HXTAL + system_clock_hxtal(); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) + system_clock_24m_hxtal(); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) + system_clock_36m_hxtal(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) + system_clock_56m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) + system_clock_96m_hxtal(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#endif /* __SYSTEM_CLOCK_HXTAL */ +} + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit(void) +{ + /* reset the RCC clock configuration to the default reset state */ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + +#ifdef GD32F10X_CL + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + + RCU_CFG1 = 0x00000000U; +#else + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | + RCU_CFG0_USBDPSC | RCU_CFG0_PLLMF_4); +#endif /* GD32F10X_CL */ + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* reset HXTALEN, CKMEN and PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x009F0000U; +#elif defined(GD32F10X_CL) + /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x00FF0000U; +#endif + + /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); + +#ifdef VECT_TAB_SRAM + nvic_vector_table_set(NVIC_VECTTAB_RAM, VECT_TAB_OFFSET); +#else + nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET); +#endif +} + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate(void) +{ + uint32_t scss; + uint32_t pllsel, predv0sel, pllmf, ck_src, idx, clk_exp; +#ifdef GD32F10X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F10X_CL */ + /* exponent of AHB, APB1 and APB2 clock divider */ + const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + + scss = GET_BITS(RCU_CFG0, 2, 3); + + switch (scss) + { + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_IRC8M_DIV2 == pllsel){ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE / 2U; + }else{ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE / 2U; + } +#elif defined(GD32F10X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(pllmf >= 15U){ + pllmf += 1U; + }else{ + pllmf += 2U; + } + + SystemCoreClock = ck_src * pllmf; + +#ifdef GD32F10X_CL + if(15U == pllmf){ + /* PLL source clock multiply by 6.5 */ + SystemCoreClock = ck_src * 6U + ck_src / 2U; + } +#endif /* GD32F10X_CL */ + + break; + + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + SystemCoreClock = SystemCoreClock >> clk_exp; +} + +#ifdef __SYSTEM_CLOCK_HXTAL +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +/*! + \brief configure the system clock to 24M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_24m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL6; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +/*! + \brief configure the system clock to 36M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_36m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL9; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL12; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +/*! + \brief configure the system clock to 56M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_56m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 14 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL14; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 14 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL14); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL18; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +/*! + \brief configure the system clock to 96M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_96m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL24; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL27; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while(0U == (RCU_CTL & RCU_CTL_PLL1STB)){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL12; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL18; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL27; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h new file mode 100644 index 0000000000..1b661b4421 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h @@ -0,0 +1,1638 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) /* Cosmic */ + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI__VFP_SUPPORT____ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200 + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h new file mode 100644 index 0000000000..2c2af69c18 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h @@ -0,0 +1,637 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ +#include + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + +#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/ +/* Cosmic specific functions */ +#include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h new file mode 100644 index 0000000000..49ded78b3d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h @@ -0,0 +1,687 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ +#include + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + +#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/ +/* Cosmic specific functions */ +#include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h new file mode 100644 index 0000000000..3a5d4c303a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h @@ -0,0 +1,367 @@ +/*! + \file gd32f10x_adc.h + \brief definitions for the ADC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_ADC_H +#define GD32F10x_ADC_H + +#include "gd32f10x.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) +#define ADC2 (ADC_BASE + 0x1800U) + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0,4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13,15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16,19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ +#define ADC_CTL0_DRES BITS(24,25) /*!< ADC data resolution */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17,19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger conversion mode for inserted channels */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0..1 */ +#define ADC_SAMPTX_SPTN BITS(0,2) /*!< channel n sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0,11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0,11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0,11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx x=0..2 */ +#define ADC_RSQX_RSQN BITS(0,4) /*!< nth conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20,23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0,4) /*!< nth conversion in inserted sequence */ +#define ADC_ISQ_IL BITS(20,21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0,15) /*!< inserted data n */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0,15) /*!< regular data */ +#define ADC_RDATA_ADC1RDTR BITS(16,31) /*!< ADC1 regular channel data */ + +/* constants definitions */ +/* adc_stat register value */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< inserted channel end of conversion */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* scan mode */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ + +/* inserted channel group convert automatically */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ + +/* ADC sync mode */ +#define CTL0_SYNCM(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* adc_ctl1 register value */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* continuous mode */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +/* for ADC0 and ADC1 regular channel */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< TIMER0 CH0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< TIMER0 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< TIMER1 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< TIMER2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< TIMER3 CH3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(6) /*!< TIMER7 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_2_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ +/* for ADC2 regular channel */ +#define ADC2_EXTTRIG_REGULAR_T2_CH0 CTL1_ETSRC(0) /*!< TIMER2 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T1_CH2 CTL1_ETSRC(1) /*!< TIMER1 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_CH0 CTL1_ETSRC(3) /*!< TIMER7 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(4) /*!< TIMER7 TRGO event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< TIMER4 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< TIMER4 CH2 event select */ + +/* external trigger mode for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +/* for ADC0 and ADC1 inserted channel */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< TIMER1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< TIMER1 CH0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< TIMER2 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< TIMER3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(6) /*!< TIMER7 CH3 event select */ +#define ADC0_1_2_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ +/* for ADC2 inserted channel */ +#define ADC2_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T3_CH2 CTL1_ETSIC(2) /*!< TIMER3 CH2 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH1 CTL1_ETSIC(3) /*!< TIMER7 CH1 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(4) /*!< TIMER7 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T4_TRGO CTL1_ETSIC(5) /*!< TIMER4 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T4_CH3 CTL1_ETSIC(6) /*!< TIMER4 CH3 event select */ + +/* adc_samptx register value */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< adc regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< adc inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* function declarations */ +/* initialization config */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* configure the ADC sync mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* DMA config */ +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); + +/* regular group and inserted group config */ +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length); + +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset); + +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* configure ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group); + +/* get channel data */ +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* watchdog config */ +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold); + +/* interrupt & flag functions */ +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); +/* get the bit state of ADCx software start conversion */ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph); +/* get the bit state of ADCx software inserted channel start conversion */ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph); +/* get the ADC interrupt bits */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); +/* clear the ADC flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); + +#endif /* GD32F10x_ADC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h new file mode 100644 index 0000000000..2963c35e9e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h @@ -0,0 +1,229 @@ +/*! + \file gd32f10x_bkp.h + \brief definitions for the BKP + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_BKP_H +#define GD32F10X_BKP_H + +#include "gd32f10x.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL REG16((BKP) + 0x30U) /*!< tamper pin control register */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0,15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0,6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ + +/* BKP_TPCTL */ +#define BKP_TPCTL_TPEN BIT(0) /*!< tamper detection enable */ +#define BKP_TPCTL_TPAL BIT(1) /*!< tamper pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER BIT(0) /*!< tamper event reset */ +#define BKP_TPCS_TIR BIT(1) /*!< tamper interrupt reset */ +#define BKP_TPCS_TPIE BIT(2) /*!< tamper interrupt enable */ +#define BKP_TPCS_TEF BIT(8) /*!< tamper event flag */ +#define BKP_TPCS_TIF BIT(9) /*!< tamper interrupt flag */ + +/* constants definitions */ +/* BKP data register number */ +typedef enum +{ + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +}bkp_data_register_enum; + +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER BKP_TPCS_TEF /*!< tamper event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER BKP_TPCS_TIF /*!< tamper interrupt flag */ +/* function declarations */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_data_read(bkp_data_register_enum register_number); + +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* select RTC output */ +void bkp_rtc_output_select(uint16_t outputsel); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(void); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(void); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(uint16_t level); + +/* interrupt & flag functions */ +/* enable tamper interrupt */ +void bkp_interrupt_enable(void); +/* disable tamper interrupt */ +void bkp_interrupt_disable(void); +/* get tamper flag state */ +FlagStatus bkp_flag_get(void); +/* clear tamper flag state */ +void bkp_flag_clear(void); +/* get tamper interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(void); +/* clear tamper interrupt flag state */ +void bkp_interrupt_flag_clear(void); + +#endif /* GD32F10X_BKP_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h new file mode 100644 index 0000000000..29b14e7451 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h @@ -0,0 +1,754 @@ +/*! + \file gd32f10x_can.h + \brief definitions for the CAN + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-11-27, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_CAN_H +#define GD32F10x_CAN_H + +#include "gd32f10x.h" + +/* CAN definitions */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ + +/* registers definitions */ +#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ + +/* CAN transmit mailbox bank */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ + +/* CAN filter bank */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ + +/* CAN receive fifo mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ + +/* bits definitions */ +/* CAN_CTL */ +#define CAN_CTL_IWMOD BIT(0) /*!< initial working mode */ +#define CAN_CTL_SLPWMOD BIT(1) /*!< sleep working mode */ +#define CAN_CTL_TFO BIT(2) /*!< transmit FIFO order */ +#define CAN_CTL_RFOD BIT(3) /*!< receive FIFO overwrite disable */ +#define CAN_CTL_ARD BIT(4) /*!< automatic retransmission disable */ +#define CAN_CTL_AWU BIT(5) /*!< automatic wakeup */ +#define CAN_CTL_ABOR BIT(6) /*!< automatic bus-off recovery */ +#define CAN_CTL_TTC BIT(7) /*!< time triggered communication */ +#define CAN_CTL_SWRST BIT(15) /*!< CAN software reset */ +#define CAN_CTL_DFZ BIT(16) /*!< CAN debug freeze */ + +/* CAN_STAT */ +#define CAN_STAT_IWS BIT(0) /*!< initial working state */ +#define CAN_STAT_SLPWS BIT(1) /*!< sleep working state */ +#define CAN_STAT_ERRIF BIT(2) /*!< error interrupt flag*/ +#define CAN_STAT_WUIF BIT(3) /*!< status change interrupt flag of wakeup from sleep working mode */ +#define CAN_STAT_SLPIF BIT(4) /*!< status change interrupt flag of sleep working mode entering */ +#define CAN_STAT_TS BIT(8) /*!< transmitting state */ +#define CAN_STAT_RS BIT(9) /*!< receiving state */ +#define CAN_STAT_LASTRX BIT(10) /*!< last sample value of rx pin */ +#define CAN_STAT_RXL BIT(11) /*!< CAN rx signal */ + +/* CAN_TSTAT */ +#define CAN_TSTAT_MTF0 BIT(0) /*!< mailbox0 transmit finished */ +#define CAN_TSTAT_MTFNERR0 BIT(1) /*!< mailbox0 transmit finished and no error */ +#define CAN_TSTAT_MAL0 BIT(2) /*!< mailbox0 arbitration lost */ +#define CAN_TSTAT_MTE0 BIT(3) /*!< mailbox0 transmit error */ +#define CAN_TSTAT_MST0 BIT(7) /*!< mailbox0 stop transmitting */ +#define CAN_TSTAT_MTF1 BIT(8) /*!< mailbox1 transmit finished */ +#define CAN_TSTAT_MTFNERR1 BIT(9) /*!< mailbox1 transmit finished and no error */ +#define CAN_TSTAT_MAL1 BIT(10) /*!< mailbox1 arbitration lost */ +#define CAN_TSTAT_MTE1 BIT(11) /*!< mailbox1 transmit error */ +#define CAN_TSTAT_MST1 BIT(15) /*!< mailbox1 stop transmitting */ +#define CAN_TSTAT_MTF2 BIT(16) /*!< mailbox2 transmit finished */ +#define CAN_TSTAT_MTFNERR2 BIT(17) /*!< mailbox2 transmit finished and no error */ +#define CAN_TSTAT_MAL2 BIT(18) /*!< mailbox2 arbitration lost */ +#define CAN_TSTAT_MTE2 BIT(19) /*!< mailbox2 transmit error */ +#define CAN_TSTAT_MST2 BIT(23) /*!< mailbox2 stop transmitting */ +#define CAN_TSTAT_NUM BITS(24,25) /*!< mailbox number */ +#define CAN_TSTAT_TME0 BIT(26) /*!< transmit mailbox0 empty */ +#define CAN_TSTAT_TME1 BIT(27) /*!< transmit mailbox1 empty */ +#define CAN_TSTAT_TME2 BIT(28) /*!< transmit mailbox2 empty */ +#define CAN_TSTAT_TMLS0 BIT(29) /*!< last sending priority flag for mailbox0 */ +#define CAN_TSTAT_TMLS1 BIT(30) /*!< last sending priority flag for mailbox1 */ +#define CAN_TSTAT_TMLS2 BIT(31) /*!< last sending priority flag for mailbox2 */ + +/* CAN_RFIFO0 */ +#define CAN_RFIFO0_RFL0 BITS(0,1) /*!< receive FIFO0 length */ +#define CAN_RFIFO0_RFF0 BIT(3) /*!< receive FIFO0 full */ +#define CAN_RFIFO0_RFO0 BIT(4) /*!< receive FIFO0 overfull */ +#define CAN_RFIFO0_RFD0 BIT(5) /*!< receive FIFO0 dequeue */ + +/* CAN_RFIFO1 */ +#define CAN_RFIFO1_RFL1 BITS(0,1) /*!< receive FIFO1 length */ +#define CAN_RFIFO1_RFF1 BIT(3) /*!< receive FIFO1 full */ +#define CAN_RFIFO1_RFO1 BIT(4) /*!< receive FIFO1 overfull */ +#define CAN_RFIFO1_RFD1 BIT(5) /*!< receive FIFO1 dequeue */ + +/* CAN_INTEN */ +#define CAN_INTEN_TMEIE BIT(0) /*!< transmit mailbox empty interrupt enable */ +#define CAN_INTEN_RFNEIE0 BIT(1) /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INTEN_RFFIE0 BIT(2) /*!< receive FIFO0 full interrupt enable */ +#define CAN_INTEN_RFOIE0 BIT(3) /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INTEN_RFNEIE1 BIT(4) /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INTEN_RFFIE1 BIT(5) /*!< receive FIFO1 full interrupt enable */ +#define CAN_INTEN_RFOIE1 BIT(6) /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INTEN_WERRIE BIT(8) /*!< warning error interrupt enable */ +#define CAN_INTEN_PERRIE BIT(9) /*!< passive error interrupt enable */ +#define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ +#define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ +#define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ + +/* CAN_ERR */ +#define CAN_ERR_WERR BIT(0) /*!< warning error */ +#define CAN_ERR_PERR BIT(1) /*!< passive error */ +#define CAN_ERR_BOERR BIT(2) /*!< bus-off error */ +#define CAN_ERR_ERRN BITS(4,6) /*!< error number */ +#define CAN_ERR_TECNT BITS(16,23) /*!< transmit error count */ +#define CAN_ERR_RECNT BITS(24,31) /*!< receive error count */ + +/* CAN_BT */ +#define CAN_BT_BAUDPSC BITS(0,9) /*!< baudrate prescaler */ +#define CAN_BT_BS1 BITS(16,19) /*!< bit segment 1 */ +#define CAN_BT_BS2 BITS(20,22) /*!< bit segment 2 */ +#define CAN_BT_SJW BITS(24,25) /*!< resynchronization jump width */ +#define CAN_BT_LCMOD BIT(30) /*!< loopback communication mode */ +#define CAN_BT_SCMOD BIT(31) /*!< silent communication mode */ + +/* CAN_TMIx */ +#define CAN_TMI_TEN BIT(0) /*!< transmit enable */ +#define CAN_TMI_FT BIT(1) /*!< frame type */ +#define CAN_TMI_FF BIT(2) /*!< frame format */ +#define CAN_TMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_TMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_TMPx */ +#define CAN_TMP_DLENC BITS(0,3) /*!< data length code */ +#define CAN_TMP_TSEN BIT(8) /*!< time stamp enable */ +#define CAN_TMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_TMDATA0x */ +#define CAN_TMDATA0_DB0 BITS(0,7) /*!< transmit data byte 0 */ +#define CAN_TMDATA0_DB1 BITS(8,15) /*!< transmit data byte 1 */ +#define CAN_TMDATA0_DB2 BITS(16,23) /*!< transmit data byte 2 */ +#define CAN_TMDATA0_DB3 BITS(24,31) /*!< transmit data byte 3 */ + +/* CAN_TMDATA1x */ +#define CAN_TMDATA1_DB4 BITS(0,7) /*!< transmit data byte 4 */ +#define CAN_TMDATA1_DB5 BITS(8,15) /*!< transmit data byte 5 */ +#define CAN_TMDATA1_DB6 BITS(16,23) /*!< transmit data byte 6 */ +#define CAN_TMDATA1_DB7 BITS(24,31) /*!< transmit data byte 7 */ + +/* CAN_RFIFOMIx */ +#define CAN_RFIFOMI_FT BIT(1) /*!< frame type */ +#define CAN_RFIFOMI_FF BIT(2) /*!< frame format */ +#define CAN_RFIFOMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_RFIFOMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_RFIFOMPx */ +#define CAN_RFIFOMP_DLENC BITS(0,3) /*!< receive data length code */ +#define CAN_RFIFOMP_FI BITS(8,15) /*!< filter index */ +#define CAN_RFIFOMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_RFIFOMDATA0x */ +#define CAN_RFIFOMDATA0_DB0 BITS(0,7) /*!< receive data byte 0 */ +#define CAN_RFIFOMDATA0_DB1 BITS(8,15) /*!< receive data byte 1 */ +#define CAN_RFIFOMDATA0_DB2 BITS(16,23) /*!< receive data byte 2 */ +#define CAN_RFIFOMDATA0_DB3 BITS(24,31) /*!< receive data byte 3 */ + +/* CAN_RFIFOMDATA1x */ +#define CAN_RFIFOMDATA1_DB4 BITS(0,7) /*!< receive data byte 4 */ +#define CAN_RFIFOMDATA1_DB5 BITS(8,15) /*!< receive data byte 5 */ +#define CAN_RFIFOMDATA1_DB6 BITS(16,23) /*!< receive data byte 6 */ +#define CAN_RFIFOMDATA1_DB7 BITS(24,31) /*!< receive data byte 7 */ + +/* CAN_FCTL */ +#define CAN_FCTL_FLD BIT(0) /*!< filter lock disable */ +#define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ + +/* CAN_FMCFG */ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ + +/* CAN_FSCFG */ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ + +/* CAN_FAFIFO */ +#define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ + +/* CAN_FW */ +#define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ + +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + +/* consts definitions */ +/* define the CAN bit position and its register index offset */ +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +#define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ +#define TSTAT_REG_OFFSET ((uint8_t)0x08U) /*!< TSTAT register offset */ +#define RFIFO0_REG_OFFSET ((uint8_t)0x0CU) /*!< RFIFO0 register offset */ +#define RFIFO1_REG_OFFSET ((uint8_t)0x10U) /*!< RFIFO1 register offset */ +#define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ + +/* CAN flags */ +typedef enum +{ + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + /* flags in TSTAT register */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + /* flags in RFIFO0 register */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + /* flags in RFIFO1 register */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + /* flags in ERR register */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +}can_flag_enum; + +/* CAN interrupt flags */ +typedef enum +{ + /* interrupt flags in STAT register */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +}can_interrupt_flag_enum; + +/* CAN initiliaze parameters struct */ +typedef struct +{ + uint8_t working_mode; /*!< CAN working mode */ + uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ + uint8_t time_segment_1; /*!< time segment 1 */ + uint8_t time_segment_2; /*!< time segment 2 */ + ControlStatus time_triggered; /*!< time triggered communication mode */ + ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ + ControlStatus auto_wake_up; /*!< automatic wake-up mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ + ControlStatus trans_fifo_order; /*!< transmit FIFO order */ + uint16_t prescaler; /*!< baudrate prescaler */ +}can_parameter_struct; + +/* CAN transmit message struct */ +typedef struct +{ + uint32_t tx_sfid; /*!< standard format frame identifier */ + uint32_t tx_efid; /*!< extended format frame identifier */ + uint8_t tx_ff; /*!< format of frame, standard or extended format */ + uint8_t tx_ft; /*!< type of frame, data or remote */ + uint8_t tx_dlen; /*!< data length */ + uint8_t tx_data[8]; /*!< transmit data */ +}can_trasnmit_message_struct; + +/* CAN receive message struct */ +typedef struct +{ + uint32_t rx_sfid; /*!< standard format frame identifier */ + uint32_t rx_efid; /*!< extended format frame identifier */ + uint8_t rx_ff; /*!< format of frame, standard or extended format */ + uint8_t rx_ft; /*!< type of frame, data or remote */ + uint8_t rx_dlen; /*!< data length */ + uint8_t rx_data[8]; /*!< receive data */ + uint8_t rx_fi; /*!< filtering index */ +} can_receive_message_struct; + +/* CAN filter parameters struct */ +typedef struct +{ + uint16_t filter_list_high; /*!< filter list number high bits*/ + uint16_t filter_list_low; /*!< filter list number low bits */ + uint16_t filter_mask_high; /*!< filter mask number high bits */ + uint16_t filter_mask_low; /*!< filter mask number low bits */ + uint16_t filter_fifo_number; /*!< receive FIFO associated with the filter */ + uint16_t filter_number; /*!< filter number */ + uint16_t filter_mode; /*!< filter mode, list or mask */ + uint16_t filter_bits; /*!< filter scale */ + ControlStatus filter_enable; /*!< filter work or not */ +}can_filter_parameter_struct; + +/* CAN errors */ +typedef enum +{ + CAN_ERROR_NONE = 0, /*!< no error */ + CAN_ERROR_FILL, /*!< fill error */ + CAN_ERROR_FORMATE, /*!< format error */ + CAN_ERROR_ACK, /*!< ACK error */ + CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ + CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ + CAN_ERROR_CRC, /*!< CRC error */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ +}can_error_enum; + +/* transmit states */ +typedef enum +{ + CAN_TRANSMIT_FAILED = 0U, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1U, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2U, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4U, /*!< no empty mailbox to be used for CAN */ +}can_transmit_state_enum; + +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + +/* CAN baudrate prescaler*/ +#define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) + +/* CAN bit segment 1*/ +#define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) + +/* CAN bit segment 2*/ +#define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) + +/* CAN resynchronization jump width*/ +#define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) + +/* CAN communication mode*/ +#define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) + +/* CAN FDATA high 16 bits */ +#define FDATA_MASK_HIGH(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) + +/* CAN FDATA low 16 bits */ +#define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) + +/* CAN1 filter start bank_number*/ +#define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) + +/* CAN transmit mailbox extended identifier*/ +#define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) + +/* CAN transmit mailbox standard identifier*/ +#define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) + +/* transmit data byte 0 */ +#define TMDATA0_DB0(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 1 */ +#define TMDATA0_DB1(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 2 */ +#define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 3 */ +#define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* transmit data byte 4 */ +#define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 5 */ +#define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 6 */ +#define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 7 */ +#define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* receive mailbox extended identifier*/ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3U, 31U) + +/* receive mailbox standrad identifier*/ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21U, 31U) + +/* receive data length */ +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0U, 3U) + +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 0 */ +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 1 */ +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 2 */ +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 3 */ +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* receive data byte 4 */ +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 5 */ +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 6 */ +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 7 */ +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4U, 6U) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* CAN errors */ +#define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) +#define CAN_ERRN_0 ERR_ERRN(0U) /* no error */ +#define CAN_ERRN_1 ERR_ERRN(1U) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2U) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3U) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4U) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5U) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6U) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7U) /*!< software error */ + +#define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ + +/* CAN communication mode */ +#define CAN_NORMAL_MODE ((uint8_t)0x00U) /*!< normal communication mode */ +#define CAN_LOOPBACK_MODE ((uint8_t)0x01U) /*!< loopback communication mode */ +#define CAN_SILENT_MODE ((uint8_t)0x02U) /*!< silent communication mode */ +#define CAN_SILENT_LOOPBACK_MODE ((uint8_t)0x03U) /*!< loopback and silent communication mode */ + +/* CAN resynchronisation jump width */ +#define CAN_BT_SJW_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_SJW_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_SJW_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_SJW_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ + +/* CAN time segment 1 */ +#define CAN_BT_BS1_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS1_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS1_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS1_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS1_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS1_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS1_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS1_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ +#define CAN_BT_BS1_9TQ ((uint8_t)0x08U) /*!< 9 time quanta */ +#define CAN_BT_BS1_10TQ ((uint8_t)0x09U) /*!< 10 time quanta */ +#define CAN_BT_BS1_11TQ ((uint8_t)0x0AU) /*!< 11 time quanta */ +#define CAN_BT_BS1_12TQ ((uint8_t)0x0BU) /*!< 12 time quanta */ +#define CAN_BT_BS1_13TQ ((uint8_t)0x0CU) /*!< 13 time quanta */ +#define CAN_BT_BS1_14TQ ((uint8_t)0x0DU) /*!< 14 time quanta */ +#define CAN_BT_BS1_15TQ ((uint8_t)0x0EU) /*!< 15 time quanta */ +#define CAN_BT_BS1_16TQ ((uint8_t)0x0FU) /*!< 16 time quanta */ + +/* CAN time segment 2 */ +#define CAN_BT_BS2_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS2_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS2_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS2_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS2_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS2_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS2_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS2_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ + +/* CAN mailbox number */ +#define CAN_MAILBOX0 ((uint8_t)0x00U) /*!< mailbox0 */ +#define CAN_MAILBOX1 ((uint8_t)0x01U) /*!< mailbox1 */ +#define CAN_MAILBOX2 ((uint8_t)0x02U) /*!< mailbox2 */ +#define CAN_NOMAILBOX ((uint8_t)0x03U) /*!< no mailbox empty */ + +/* CAN frame format */ +#define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ +#define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ + +/* CAN receive fifo */ +#define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ +#define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ + +/* frame number of receive fifo */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ + +#define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ +#define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ + +/* CAN working mode */ +#define CAN_MODE_INITIALIZE ((uint8_t)0x01U) /*!< CAN initialize mode */ +#define CAN_MODE_NORMAL ((uint8_t)0x02U) /*!< CAN normal mode */ +#define CAN_MODE_SLEEP ((uint8_t)0x04U) /*!< CAN sleep mode */ + +/* filter bits */ +#define CAN_FILTERBITS_16BIT ((uint8_t)0x00U) /*!< CAN filter 16 bits */ +#define CAN_FILTERBITS_32BIT ((uint8_t)0x01U) /*!< CAN filter 32 bits */ + +/* filter mode */ +#define CAN_FILTERMODE_MASK ((uint8_t)0x00U) /*!< mask mode */ +#define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ + +/* filter 16 bits mask */ +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ + +/* frame type */ +#define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ +#define CAN_FT_REMOTE ((uint32_t)0x00000002U) /*!< remote frame */ + +/* CAN timeout */ +#define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ + +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + +/* function declarations */ +/* deinitialize CAN */ +void can_deinit(uint32_t can_periph); +/* initialize CAN struct */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +/* CAN filter init */ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); +/* set can1 fliter start bank number */ +void can1_filter_start_bank(uint8_t start_bank); +/* enable functions */ +/* CAN debug freeze enable */ +void can_debug_freeze_enable(uint32_t can_periph); +/* CAN debug freeze disable */ +void can_debug_freeze_disable(uint32_t can_periph); +/* CAN time trigger mode enable */ +void can_time_trigger_mode_enable(uint32_t can_periph); +/* CAN time trigger mode disable */ +void can_time_trigger_mode_disable(uint32_t can_periph); + +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); +/* CAN receive message */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); +/* CAN release fifo */ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); +/* CAN receive message length */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); +/* CAN working mode */ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); +/* CAN wakeup from sleep mode */ +ErrStatus can_wakeup(uint32_t can_periph); + +/* CAN get error */ +can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); +/* CAN get flag state */ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); +/* CAN clear flag state */ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN get interrupt flag state */ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); +/* CAN clear interrupt flag state */ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag); + +#endif /* GD32F10x_CAN_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h new file mode 100644 index 0000000000..107b527456 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h @@ -0,0 +1,80 @@ +/*! + \file gd32f10x_crc.h + \brief definitions for the CRC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_CRC_H +#define GD32F10X_CRC_H + +#include "gd32f10x.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0,31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0,7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + +/* function declarations */ +/* deinit CRC calculation unit */ +void crc_deinit(void); + +/* reset data register to the value of initializaiton data register */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); + +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size); + +#endif /* GD32F10X_CRC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h new file mode 100644 index 0000000000..fc9a16d47c --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h @@ -0,0 +1,249 @@ +/*! + \file gd32f10x_dac.h + \brief definitions for the DAC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_DAC_H +#define GD32F10X_DAC_H + +#include "gd32f10x.h" + +/* DACx(x=0,1) definitions */ +#define DAC DAC_BASE +#define DAC0 0U +#define DAC1 1U + +/* registers definitions */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ + +/* bits definitions */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ + +/* DAC_SWT */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ + +/* DAC0_R12DH */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ + +/* DAC0_L12DH */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ + +/* DAC0_R8DH */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ + +/* DAC1_R12DH */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ + +/* DAC1_L12DH */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ + +/* DAC1_R8DH */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ + +/* DACC_R12DH */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ + +/* DACC_L12DH */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ + +/* DACC_R8DH */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ + +/* DAC0_DO */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ + +/* DAC1_DO */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ + +/* constants definitions */ +/* DAC trigger source */ +#define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define DAC_TRIGGER_T7_TRGO CTL_DTSEL(1) /*!< TIMER7 TRGO */ +#elif defined(GD32F10X_CL) +#define DAC_TRIGGER_T2_TRGO CTL_DTSEL(1) /*!< TIMER2 TRGO */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ + +/* DAC noise wave mode */ +#define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ + +/* DAC noise wave bit width */ +#define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ + +/* unmask LFSR bits in DAC LFSR noise mode */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ + +/* DAC data alignment */ +#define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12b alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12b alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8b alignment */ +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DAC */ +void dac_deinit(void); +/* enable DAC */ +void dac_enable(uint32_t dac_periph); +/* disable DAC */ +void dac_disable(uint32_t dac_periph); +/* enable DAC DMA */ +void dac_dma_enable(uint32_t dac_periph); +/* disable DAC DMA */ +void dac_dma_disable(uint32_t dac_periph); +/* enable DAC output buffer */ +void dac_output_buffer_enable(uint32_t dac_periph); +/* disable DAC output buffer */ +void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* DAC trigger configuration */ +/* enable DAC trigger */ +void dac_trigger_enable(uint32_t dac_periph); +/* disable DAC trigger */ +void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* enable DAC software trigger */ +void dac_software_trigger_enable(uint32_t dac_periph); +/* disable DAC software trigger */ +void dac_software_trigger_disable(uint32_t dac_periph); + +/* DAC wave mode configuration */ +/* configure DAC wave mode */ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); +/* configure DAC wave bit width */ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); +/* configure DAC LFSR noise mode */ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); +/* configure DAC triangle noise mode */ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); + +/* DAC concurrent mode configuration */ +/* enable DAC concurrent mode */ +void dac_concurrent_enable(void); +/* disable DAC concurrent mode */ +void dac_concurrent_disable(void); +/* enable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_enable(void); +/* disable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_disable(void); +/* enable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_enable(void); +/* disable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); + +#endif /* GD32F10X_DAC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h new file mode 100644 index 0000000000..cf51f0ed06 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h @@ -0,0 +1,152 @@ +/*! + \file gd32f10x_dbg.h + \brief definitions for the DBG + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-07-01, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_DBG_H +#define GD32F10X_DBG_H + +#include "gd32f10x.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL REG32(DBG + 0x04U) /*!< DBG control register */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ + +/* DBG_CTL */ +#define DBG_CTL_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL_TRACE_IOEN BIT(5) /*!< enable trace pin assignment */ +#define DBG_CTL_TRACE_MODE BITS(6,7) /*!< trace pin mode selection */ +#define DBG_CTL_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL_TIMER7_HOLD BIT(17) /*!< hold TIMER7 counter when core is halted */ +#define DBG_CTL_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F10X_CL +#define DBG_CTL_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define DBG_CTL_TIMER11_HOLD BIT(25) /*!< hold TIMER11 counter when core is halted */ +#define DBG_CTL_TIMER12_HOLD BIT(26) /*!< hold TIMER12 counter when core is halted */ +#define DBG_CTL_TIMER13_HOLD BIT(27) /*!< hold TIMER13 counter when core is halted */ +#define DBG_CTL_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ +#define DBG_CTL_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ +#define DBG_CTL_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F10X_XD */ + +/* constants definitions */ +/* debug hold when core is halted */ +typedef enum +{ + DBG_FWDGT_HOLD = BIT(8), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = BIT(9), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = BIT(10), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = BIT(11), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = BIT(12), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = BIT(13), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = BIT(14), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = BIT(15), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = BIT(16), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = BIT(17), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = BIT(18), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = BIT(19), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = BIT(20), /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F10X_CL + DBG_CAN1_HOLD = BIT(21), /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F10X_CL */ +#if (defined(GD32F10X_XD) || defined(GD32F10X_CL)) + DBG_TIMER11_HOLD = BIT(25), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = BIT(26), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = BIT(27), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = BIT(28), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = BIT(29), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = BIT(30), /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F10X_XD || GD32F10X_CL*/ +}dbg_periph_enum; + +/* DBG low power mode configurations */ +#define DBG_LOW_POWER_SLEEP DBG_CTL_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* DBG_CTL0_TRACE_MODE configurations */ +#define CTL_TRACE_MODE(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) +#define TRACE_MODE_ASYNC CTL_TRACE_MODE(0) /*!< trace pin used for async mode */ +#define TRACE_MODE_SYNC_DATASIZE_1 CTL_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ +#define TRACE_MODE_SYNC_DATASIZE_2 CTL_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ +#define TRACE_MODE_SYNC_DATASIZE_4 CTL_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ + +/* function declarations */ +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* low power behavior configuration */ +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* peripheral behavior configuration */ +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +/* trace pin assignment configuration */ +/* enable trace pin assignment */ +void dbg_trace_pin_enable(void); +/* disable trace pin assignment */ +void dbg_trace_pin_disable(void); +/* set trace pin mode */ +void dbg_trace_pin_mode_set(uint32_t trace_mode); + +#endif /* GD32F10X_DBG_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h new file mode 100644 index 0000000000..a183117fe8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h @@ -0,0 +1,289 @@ +/*! + \file gd32f10x_dma.h + \brief definitions for the DMA + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-10-30, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_DMA_H +#define GD32F10X_DMA_H + +#include "gd32f10x.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT, x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ + +/* DMA_CHxPADDR, x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ + +/* DMA_CHxMADDR, x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum +{ + DMA_CH0 = 0, /*!< DMA channel 0 */ + DMA_CH1, /*!< DMA channel 1 */ + DMA_CH2, /*!< DMA channel 2 */ + DMA_CH3, /*!< DMA channel 3 */ + DMA_CH4, /*!< DMA channel 4 */ + DMA_CH5, /*!< DMA channel 5 */ + DMA_CH6 /*!< DMA channel 6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x00U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x01U) /*!< read from memory and write to peripheral */ +/* circular mode */ +#define DMA_CIRCULAR_MODE_DISABLE ((uint32_t)0x00000000U) /*!< circular mode disable */ +#define DMA_CIRCULAR_MODE_ENABLE ((uint32_t)0x00000001U) /*!< circular mode enable */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8,9) & ((regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0U) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1U) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2U) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10,11) & ((regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0U) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1U) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2U) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12,13) & ((regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0U) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1U) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2U) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3U) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) /*!< disable memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) /*!< enable memory to memory mode */ + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* DMA deinitialization and initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA struct with the default values */ +void dma_struct_para_init(dma_parameter_struct* init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increasement algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increasement algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the flag of a DMA channel */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the interrupt flag of a DMA channel */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +#endif /* GD32F10X_DMA_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h new file mode 100644 index 0000000000..3776adb59b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h @@ -0,0 +1,1497 @@ +/*! + \file gd32f10x_enet.h + \brief definitions for the ENET + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_ENET_H +#define GD32F10x_ENET_H + +#include "gd32f10x.h" +#include + +#define IF_USE_EXTERNPHY_LIB 0 +#if (1 == IF_USE_EXTERNPHY_LIB) +#include "phy.h" +#endif + +#ifndef ENET_RXBUF_NUM +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ +#endif + +#ifndef ENET_TXBUF_NUM +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ +#endif + +#ifndef ENET_RXBUF_SIZE +#define ENET_RXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet receive buffer size */ +#endif + +#ifndef ENET_TXBUF_SIZE +#define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ +#endif + +/* #define USE_DELAY */ + +#ifndef _PHY_H_ +#define DP83848 0 +#define LAN8700 1 +#define PHY_TYPE DP83848 + +#define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ + +/* PHY read write timeouts */ +#define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ +#define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ + +/* PHY delay */ +#define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ +#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ + +/* PHY register address */ +#define PHY_REG_BCR 0U /*!< tranceiver basic control register */ +#define PHY_REG_BSR 1U /*!< tranceiver basic status register */ + +/* PHY basic control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ + +#if(PHY_TYPE == LAN8700) +#define PHY_SR 31U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#elif(PHY_TYPE == DP83848) +#define PHY_SR 16U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#endif /* PHY_TYPE */ + +#endif /* _PHY_H_ */ + + +/* ENET definitions */ +#define ENET ENET_BASE + +/* registers definitions */ +#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ +#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ + +/* bits definitions */ +/* ENET_MAC_CFG */ +#define ENET_MAC_CFG_REN BIT(2) /*!< receiver enable */ +#define ENET_MAC_CFG_TEN BIT(3) /*!< transmitter enable */ +#define ENET_MAC_CFG_DFC BIT(4) /*!< defferal check */ +#define ENET_MAC_CFG_BOL BITS(5,6) /*!< back-off limit */ +#define ENET_MAC_CFG_APCD BIT(7) /*!< automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD BIT(9) /*!< retry disable */ +#define ENET_MAC_CFG_IPFCO BIT(10) /*!< IP frame checksum offload */ +#define ENET_MAC_CFG_DPM BIT(11) /*!< duplex mode */ +#define ENET_MAC_CFG_LBM BIT(12) /*!< loopback mode */ +#define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ +#define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ +#define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ +#define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ + +/* ENET_MAC_FRMF */ +#define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ +#define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + +/* ENET_MAC_HLH */ +#define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ + +/* ENET_MAC_HLL */ +#define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ + +/* ENET_MAC_PHY_CTL */ +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + +/* ENET_MAC_PHY_DATA */ +#define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ + +/* ENET_MAC_FCTL */ +#define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ +#define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ + +/* ENET_MAC_FCTH */ +#define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ +#define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ + +/* ENET_MAC_VLT */ +#define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ + +/* ENET_MAC_RWFF */ +#define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ + +/* ENET_MAC_WUM */ +#define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ +#define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ +#define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ +#define ENET_MAC_WUM_MPKR BIT(5) /*!< magic packet received */ +#define ENET_MAC_WUM_WUFR BIT(6) /*!< wakeup frame received */ +#define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ +#define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ + +/* ENET_MAC_INTF */ +#define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ +#define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ +#define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ +#define ENET_MAC_INTF_MSCT BIT(6) /*!< MSC transmit status */ +#define ENET_MAC_INTF_TMST BIT(9) /*!< timestamp trigger status */ + +/* ENET_MAC_INTMSK */ +#define ENET_MAC_INTMSK_WUMIM BIT(3) /*!< WUM interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM BIT(9) /*!< timestamp trigger interrupt mask */ + +/* ENET_MAC_ADDR0H */ +#define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ +#define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ + +/* ENET_MAC_ADDR0L */ +#define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ + +/* ENET_MAC_ADDR1H */ +#define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR1L */ +#define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ + +/* ENET_MAC_ADDR2H */ +#define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ +#define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR2L */ +#define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ + +/* ENET_MAC_ADDR3H */ +#define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ +#define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR3H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR3H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR3L */ +#define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ + +/* ENET_MSC_CTL */ +#define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ +#define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ +#define ENET_MSC_CTL_RTOR BIT(2) /*!< reset on read */ +#define ENET_MSC_CTL_MCFZ BIT(3) /*!< MSC counter freeze */ + +/* ENET_MSC_RINTF */ +#define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ +#define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ +#define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ + +/* ENET_MSC_TINTF */ +#define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ +#define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ +#define ENET_MSC_TINTF_TGF BIT(21) /*!< transmitted good frames */ + +/* ENET_MSC_RINTMSK */ +#define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ + +/* ENET_MSC_TINTMSK */ +#define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ + +/* ENET_MSC_SCCNT */ +#define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ + +/* ENET_MSC_MSCCNT */ +#define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ + +/* ENET_MSC_TGFCNT */ +#define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ + +/* ENET_MSC_RFCECNT */ +#define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ + +/* ENET_MSC_RFAECNT */ +#define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ + +/* ENET_MSC_RGUFCNT */ +#define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ + +/* ENET_PTP_TSCTL */ +#define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI BIT(2) /*!< timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU BIT(3) /*!< timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN BIT(4) /*!< timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU BIT(5) /*!< timestamp addend register update */ + +/* ENET_PTP_SSINC */ +#define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ + +/* ENET_PTP_TSH */ +#define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ + +/* ENET_PTP_TSL */ +#define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ +#define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ + +/* ENET_PTP_TSUH */ +#define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ + +/* ENET_PTP_TSUL */ +#define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ +#define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ + +/* ENET_PTP_TSADDEND */ +#define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ + +/* ENET_PTP_ETH */ +#define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ + +/* ENET_PTP_ETL */ +#define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ + +/* ENET_DMA_BCTL */ +#define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ +#define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ +#define ENET_DMA_BCTL_DPSL BITS(2,6) /*!< descriptor skip length */ +#define ENET_DMA_BCTL_PGBL BITS(8,13) /*!< programmable burst length */ +#define ENET_DMA_BCTL_RTPR BITS(14,15) /*!< RxDMA and TxDMA transfer priority ratio */ +#define ENET_DMA_BCTL_FB BIT(16) /*!< fixed Burst */ +#define ENET_DMA_BCTL_RXDP BITS(17,22) /*!< RxDMA PGBL */ +#define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ +#define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ +#define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ + +/* ENET_DMA_TPEN */ +#define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ + +/* ENET_DMA_RPEN */ +#define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ + +/* ENET_DMA_RDTADDR */ +#define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ + +/* ENET_DMA_TDTADDR */ +#define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ + +/* ENET_DMA_STAT */ +#define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ +#define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ +#define ENET_DMA_STAT_TBU BIT(2) /*!< transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT BIT(3) /*!< transmit jabber timeout status */ +#define ENET_DMA_STAT_RO BIT(4) /*!< receive overflow status */ +#define ENET_DMA_STAT_TU BIT(5) /*!< transmit underflow status */ +#define ENET_DMA_STAT_RS BIT(6) /*!< receive status */ +#define ENET_DMA_STAT_RBU BIT(7) /*!< receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS BIT(8) /*!< receive process stopped status */ +#define ENET_DMA_STAT_RWT BIT(9) /*!< receive watchdog timeout status */ +#define ENET_DMA_STAT_ET BIT(10) /*!< early transmit status */ +#define ENET_DMA_STAT_FBE BIT(13) /*!< fatal bus error status */ +#define ENET_DMA_STAT_ER BIT(14) /*!< early receive status */ +#define ENET_DMA_STAT_AI BIT(15) /*!< abnormal interrupt summary */ +#define ENET_DMA_STAT_NI BIT(16) /*!< normal interrupt summary */ +#define ENET_DMA_STAT_RP BITS(17,19) /*!< receive process state */ +#define ENET_DMA_STAT_TP BITS(20,22) /*!< transmit process state */ +#define ENET_DMA_STAT_EB BITS(23,25) /*!< error bits status */ +#define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ +#define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ +#define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ + +/* ENET_DMA_CTL */ +#define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ +#define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ +#define ENET_DMA_CTL_RTHC BITS(3,4) /*!< receive threshold control */ +#define ENET_DMA_CTL_FUF BIT(6) /*!< forward undersized good frames */ +#define ENET_DMA_CTL_FERF BIT(7) /*!< forward error frames */ +#define ENET_DMA_CTL_STE BIT(13) /*!< start/stop transmission enable */ +#define ENET_DMA_CTL_TTHC BITS(14,16) /*!< transmit threshold control */ +#define ENET_DMA_CTL_FTF BIT(20) /*!< flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD BIT(21) /*!< transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ + +/* ENET_DMA_INTEN */ +#define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE BIT(2) /*!< transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE BIT(3) /*!< transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE BIT(4) /*!< receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE BIT(5) /*!< transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE BIT(6) /*!< receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE BIT(7) /*!< receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE BIT(8) /*!< receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE BIT(9) /*!< receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE BIT(10) /*!< early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE BIT(13) /*!< fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ + +/* ENET_DMA_MFBOCNT */ +#define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ +#define ENET_DMA_MFBOCNT_OBMFC BIT(16) /* Overflow bit for missed frame counter */ +#define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ +#define ENET_DMA_MFBOCNT_OBFOC BIT(28) /*!< Overflow bit for FIFO overflow counter */ + +/* ENET_DMA_CTDADDR */ +#define ENET_DMA_CTDADDR_TDAP BITS(0,31) /*!< transmit descriptor address pointer */ + +/* ENET_DMA_CRDADDR */ +#define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ + +/* ENET_DMA_CTBADDR */ +#define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ + +/* ENET_DMA_CRBADDR */ +#define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ + +/* ENET DMA Tx descriptor TDES0 */ +#define ENET_TDES0_DB BIT(0) /*!< deferred */ +#define ENET_TDES0_UFE BIT(1) /*!< underflow error */ +#define ENET_TDES0_EXD BIT(2) /*!< excessive deferral */ +#define ENET_TDES0_COCNT BITS(3,6) /*!< collision count */ +#define ENET_TDES0_VFRM BIT(7) /*!< VLAN frame */ +#define ENET_TDES0_ECO BIT(8) /*!< excessive collision */ +#define ENET_TDES0_LCO BIT(9) /*!< late collision */ +#define ENET_TDES0_NCA BIT(10) /*!< no carrier */ +#define ENET_TDES0_LCA BIT(11) /*!< loss of carrier */ +#define ENET_TDES0_IPPE BIT(12) /*!< IP payload error */ +#define ENET_TDES0_FRMF BIT(13) /*!< frame flushed */ +#define ENET_TDES0_JT BIT(14) /*!< jabber timeout */ +#define ENET_TDES0_ES BIT(15) /*!< error summary */ +#define ENET_TDES0_IPHE BIT(16) /*!< IP header error */ +#define ENET_TDES0_TTMSS BIT(17) /*!< transmit timestamp status */ +#define ENET_TDES0_TCHM BIT(20) /*!< the second address chained mode */ +#define ENET_TDES0_TERM BIT(21) /*!< transmit end of ring mode*/ +#define ENET_TDES0_CM BITS(22,23) /*!< checksum mode */ +#define ENET_TDES0_TTSEN BIT(25) /*!< transmit timestamp function enable */ +#define ENET_TDES0_DPAD BIT(26) /*!< disable adding pad */ +#define ENET_TDES0_DCRC BIT(27) /*!< disable CRC */ +#define ENET_TDES0_FSG BIT(28) /*!< first segment */ +#define ENET_TDES0_LSG BIT(29) /*!< last segment */ +#define ENET_TDES0_INTC BIT(30) /*!< interrupt on completion */ +#define ENET_TDES0_DAV BIT(31) /*!< DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ +#define ENET_TDES1_TB1S BITS(0,12) /*!< transmit buffer 1 size */ +#define ENET_TDES1_TB2S BITS(16,28) /*!< transmit buffer 2 size */ + +/* ENET DMA Tx descriptor TDES2 */ +#define ENET_TDES2_TB1AP BITS(0,31) /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES3 */ +#define ENET_TDES3_TB2AP BITS(0,31) /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */ + +/* ENET DMA Rx descriptor RDES0 */ +#define ENET_RDES0_PCERR BIT(0) /*!< payload checksum error */ +#define ENET_RDES0_CERR BIT(1) /*!< CRC error */ +#define ENET_RDES0_DBERR BIT(2) /*!< dribble bit error */ +#define ENET_RDES0_RERR BIT(3) /*!< receive error */ +#define ENET_RDES0_RWDT BIT(4) /*!< receive watchdog timeout */ +#define ENET_RDES0_FRMT BIT(5) /*!< frame type */ +#define ENET_RDES0_LCO BIT(6) /*!< late collision */ +#define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ +#define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ +#define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ +#define ENET_RDES0_LERR BIT(12) /*!< length error */ +#define ENET_RDES0_SAFF BIT(13) /*!< SA filter fail */ +#define ENET_RDES0_DERR BIT(14) /*!< descriptor error */ +#define ENET_RDES0_ERRS BIT(15) /*!< error summary */ +#define ENET_RDES0_FRML BITS(16,29) /*!< frame length */ +#define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ +#define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ +#define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ +#define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ +#define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ +#define ENET_RDES1_RB2S BITS(16,28) /*!< receive buffer 2 size */ +#define ENET_RDES1_DINTC BIT(31) /*!< disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 */ +#define ENET_RDES2_RB1AP BITS(0,31) /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */ + +/* ENET DMA Rx descriptor RDES3 */ +#define ENET_RDES3_RB2AP BITS(0,31) /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */ + +/* constants definitions */ +/* define bit position and its register index offset */ +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* ENET clock range judgement */ +#define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) + +/* define MAC address configuration and reference address */ +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x40U) +#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) + +/* register offset */ +#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ + +#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ + +/* ENET status flag get */ +typedef enum +{ + /* ENET_MAC_WUM register */ + ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + /* ENET_MAC_FCTL register */ + ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ + /* ENET_MAC_INTF register */ + ENET_MAC_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_EB_DMA_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U), /*!< error during data transfer by RxDMA/TxDMA flag */ + ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U), /*!< error during write/read transfer flag */ + ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ + ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_flag_enum; + +/* ENET stutus flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_flag_clear_enum; + +/* ENET interrupt enable/disable */ +typedef enum +{ + /* ENET_MAC_INTMSK register */ + ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ + ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ + /* ENET_MSC_RINTMSK register */ + ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ + ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ + ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ + /* ENET_MSC_TINTMSK register */ + ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ + ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ + ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ + /* ENET_DMA_INTEN register */ + ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ + ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ + ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ + ENET_DMA_INT_TJTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U), /*!< transmit jabber timeout interrupt enable */ + ENET_DMA_INT_ROIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U), /*!< receive overflow interrupt enable */ + ENET_DMA_INT_TUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U), /*!< transmit underflow interrupt enable */ + ENET_DMA_INT_RIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U), /*!< receive interrupt enable */ + ENET_DMA_INT_RBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U), /*!< receive buffer unavailable interrupt enable */ + ENET_DMA_INT_RPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U), /*!< receive process stopped interrupt enable */ + ENET_DMA_INT_RWTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U), /*!< receive watchdog timeout interrupt enable */ + ENET_DMA_INT_ETIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U), /*!< early transmit interrupt enable */ + ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ + ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ + ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ +}enet_int_enum; + +/* ENET interrupt flag get */ +typedef enum +{ + /* ENET_MAC_INTF register */ + ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_INT_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_INT_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_INT_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_INT_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_INT_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_INT_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_INT_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_INT_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_INT_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_int_flag_enum; + +/* ENET interrupt flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_int_flag_clear_enum; + +/* current RX/TX descriptor/buffer/descriptor table address get */ +typedef enum +{ + ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ + ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ + ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ + ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ + ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ + ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ +}enet_desc_reg_enum; + +/* MAC statistics counter get */ +typedef enum +{ + ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ + ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ + ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ + ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ + ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ + ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ +}enet_msc_counter_enum; + +/* function option, used for ENET initialization */ +typedef enum +{ + FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ + DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ + DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ + DMA_ARBITRATION_OPTION = BIT(3), /*!< configure the DMA arbitration related parameters */ + STORE_OPTION = BIT(4), /*!< configure the store forward mode related parameters */ + DMA_OPTION = BIT(5), /*!< configure the DMA control related parameters */ + VLAN_OPTION = BIT(6), /*!< configure the VLAN tag related parameters */ + FLOWCTL_OPTION = BIT(7), /*!< configure the flow control related parameters */ + HASHH_OPTION = BIT(8), /*!< configure the hash list high 32-bit related parameters */ + HASHL_OPTION = BIT(9), /*!< configure the hash list low 32-bit related parameters */ + FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ + HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ + TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ + INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ +}enet_option_enum; + +/* phy mode and mac loopback configurations */ +typedef enum +{ + ENET_AUTO_NEGOTIATION = 0x01u, /*!< PHY auto negotiation */ + ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ + ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ + ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ +}enet_mediamode_enum; + +/* IP frame checksum function */ +typedef enum +{ + ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ + ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped */ +}enet_chksumconf_enum; + +/* received frame filter function */ +typedef enum +{ + ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ + ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ + ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ + ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ +}enet_frmrecept_enum; + +/* register group value get */ +typedef enum +{ + ALL_MAC_REG = 0, /*!< MAC register group */ + ALL_MSC_REG = 22, /*!< MSC register group */ + ALL_PTP_REG = 33, /*!< PTP register group */ + ALL_DMA_REG = 44, /*!< DMA register group */ +}enet_registers_type_enum; + +/* dma direction select */ +typedef enum +{ + ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ + ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ +}enet_dmadirection_enum; + +/* PHY operation direction select */ +typedef enum +{ + ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ + ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ +}enet_phydirection_enum; + +/* register operation direction select */ +typedef enum +{ + ENET_REG_READ, /*!< read register */ + ENET_REG_WRITE /*!< write register */ +}enet_regdirection_enum; + +/* ENET MAC addresses */ +typedef enum +{ + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ +}enet_macaddress_enum; + +/* descriptor information */ +typedef enum +{ + TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ + TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ + RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ + RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ + RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ + RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ +}enet_descstate_enum; + +/* structure for initialization of the ENET */ +typedef struct +{ + uint32_t option_enable; /*!< select which function to configure */ + uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ + uint32_t dma_maxburst; /*!< DMA max burst related parameters */ + uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ + uint32_t store_forward_mode; /*!< store forward mode related parameters */ + uint32_t dma_function; /*!< DMA control related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t flow_control; /*!< flow control related parameters */ + uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ + uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ + uint32_t framesfilter_mode; /*!< frame filter control related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t timer_config; /*!< frame timer related parameters */ + uint32_t interframegap; /*!< inter frame gap related parameters */ +}enet_initpara_struct; + +/* structure for ENET DMA desciptors */ +typedef struct +{ + uint32_t status; /*!< status */ + uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ + uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ + uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ +} enet_descriptors_struct; + +/* structure of PTP system time */ +typedef struct +{ + uint32_t second; /*!< second of system time */ + uint32_t nanosecond; /*!< nanosecond of system time */ + uint32_t sign; /*!< sign of system time */ +}enet_ptp_systime_struct; + +/* mac_cfg register value */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ + +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ +#define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ +#define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ +#define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ + +#define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ +#define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ + +#define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ +#define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ + +#define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ +#define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ + +#define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ +#define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ + +#define ENET_RECEIVEOWN_ENABLE ((uint32_t)0x00000000U) /*!< the MAC receives all packets that are given by the PHY while transmitting */ +#define ENET_RECEIVEOWN_DISABLE ENET_MAC_CFG_ROD /*!< the MAC disables the reception of frames in half-duplex mode */ + +#define ENET_LOOPBACKMODE_ENABLE ENET_MAC_CFG_LBM /*!< the MAC operates in loopback mode at the MII */ +#define ENET_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000U) /*!< the MAC operates in normal mode */ + +#define ENET_MODE_FULLDUPLEX ENET_MAC_CFG_DPM /*!< full-duplex mode enable */ +#define ENET_MODE_HALFDUPLEX ((uint32_t)0x00000000U) /*!< half-duplex mode enable */ + +#define ENET_CHECKSUMOFFLOAD_ENABLE ENET_MAC_CFG_IPFCO /*!< IP frame checksum offload function enabled for received IP frame */ +#define ENET_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000U) /*!< the checksum offload function in the receiver is disabled */ + +#define ENET_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000U) /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/ +#define ENET_RETRYTRANSMISSION_DISABLE ENET_MAC_CFG_RTD /*!< the MAC attempts only 1 transmission */ + +#define ENET_AUTO_PADCRC_DROP_ENABLE ENET_MAC_CFG_APCD /*!< the MAC strips the Pad/FCS field on received frames */ +#define ENET_AUTO_PADCRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< the MAC forwards all received frames without modify it */ +#define ENET_AUTO_PADCRC_DROP ENET_MAC_CFG_APCD /*!< the function of the MAC strips the Pad/FCS field on received frames */ + +#define ENET_DEFERRALCHECK_ENABLE ENET_MAC_CFG_DFC /*!< the deferral check function is enabled in the MAC */ +#define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ + +/* mac_frmf register value */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ +#define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ +#define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ + +#define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ +#define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ + +#define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ +#define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ +#define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ +#define ENET_SRC_FILTER ENET_MAC_FRMF_SAFLT /*!< filter source address function */ +#define ENET_SRC_FILTER_INVERSE ENET_MAC_FRMF_SAIFLT /*!< inverse source address filtering result function */ + +#define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ +#define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ + +#define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ + +#define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ +#define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ + +#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ +#define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ +#define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ +#define ENET_MULTICAST_FILTER_NONE ENET_MAC_FRMF_MFD /*!< all multicast frames are passed */ +#define ENET_MULTICAST_FILTER_PASS ENET_MAC_FRMF_MFD /*!< pass all multicast frames function */ +#define ENET_MULTICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HMF /*!< HASH multicast filter function */ +#define ENET_FILTER_MODE_EITHER ENET_MAC_FRMF_HPFLT /*!< HASH or perfect filter function */ + +#define ENET_UNICAST_FILTER_EITHER (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT) /*!< pass unicast frames that match either the perfect or the hash filtering */ +#define ENET_UNICAST_FILTER_HASH ENET_MAC_FRMF_HUF /*!< pass unicast frames that match the hash filtering */ +#define ENET_UNICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass unicast frames that match the perfect filtering */ +#define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ + +/* mac_phy_ctl register value */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ + +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ + +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ + +/* mac_phy_data register value */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ + +/* mac_fctl register value */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ + +#define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE ENET_MAC_FCTL_DZQP /*!< the automatic zero-quanta generation function */ + +#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ +#define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ + +#define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ +#define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ +#define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ + +#define ENET_TX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_TFCEN /*!< enable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< disable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL ENET_MAC_FCTL_TFCEN /*!< the flow control operation in the MAC */ + +#define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ +/* mac_vlt register value */ +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + +#define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ +#define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ + +/* mac_wum register value */ +#define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ +#define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ +#define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + +/* mac_addr0h register value */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ + +/* mac_addrxh register value, x = 1,2,3 */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ + +#define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ +#define ENET_ADDRESS_MASK_BYTE2 BIT(26) /*!< low register bits [23:16] */ +#define ENET_ADDRESS_MASK_BYTE3 BIT(27) /*!< low register bits [31:24] */ +#define ENET_ADDRESS_MASK_BYTE4 BIT(28) /*!< high register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ + +#define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + +/* mac_fcth register value */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ +#define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ +#define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ +#define ENET_ACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFA(3) /*!< threshold level is 1024 bytes */ +#define ENET_ACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFA(4) /*!< threshold level is 1280 bytes */ +#define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ +#define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ + +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4))<<8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ +#define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ +#define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFD(3) /*!< threshold level is 1024 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFD(4) /*!< threshold level is 1280 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFD(5) /*!< threshold level is 1536 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFD(6) /*!< threshold level is 1792 bytes */ + +/* msc_ctl register value */ +#define ENET_MSC_COUNTER_STOP_ROLLOVER ENET_MSC_CTL_CTSR /*!< counter stop rollover */ +#define ENET_MSC_RESET_ON_READ ENET_MSC_CTL_RTOR /*!< reset on read */ +#define ENET_MSC_COUNTERS_FREEZE ENET_MSC_CTL_MCFZ /*!< MSC counter freeze */ + +/* ptp_tsctl register value */ +#define ENET_RXTX_TIMESTAMP ENET_PTP_TSCTL_TMSEN /*!< enable timestamp function for transmit and receive frames */ +#define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ + +/* ptp_ssinc register value */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ + +/* ptp_tsl register value */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ + +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ + +/* ptp_tsul register value */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ + +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ + +/* dma_bctl register value */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ + +/* dma_stat register value */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ +#define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ + +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ +#define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ + +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ + +/* dma_ctl register value */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ + +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES DMA_CTL_TTHC(3) /*!< threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES DMA_CTL_TTHC(4) /*!< threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES DMA_CTL_TTHC(5) /*!< threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES DMA_CTL_TTHC(6) /*!< threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ + +#define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ + +#define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ + +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ + +#define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ + +#define ENET_FORWARD_ERRFRAMES_ENABLE ENET_DMA_CTL_FERF /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF<<2) /*!< the function that all frame received with error except runt error are forwarded to memory */ + +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE ENET_DMA_CTL_FUF /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF<<2) /*!< the function that forwarding undersized good frames */ + +#define ENET_SECONDFRAME_OPT_ENABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ + +/* dma_mfbocnt register value */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ + +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ + +/* dma tx descriptor tdes0 register value */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ + +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ + +/* dma tx descriptor tdes1 register value */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ + +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ + +/* dma rx descriptor rdes0 register value */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ + +/* dma rx descriptor rdes1 register value */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ + +#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ + +#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ + +/* dma rx descriptor rdes4 register value */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ + +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ + +/* ENET register mask value */ +#define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ +#define MAC_FCTL_MASK ((uint32_t)0x0000FF41U) /*!< ENET_MAC_FCTL register mask */ +#define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ +#define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ + +#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ + +typedef enum{ + ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ +}enet_ptp_function_enum; + + +/* ENET remote wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ + +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ + +/* ENET delay timeout */ +#define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ +#define ENET_RESET_TO ((uint32_t)0x000004FFU) /*!< ENET reset timeout */ + +/* function declarations */ +/* main function */ +/* deinitialize the ENET, and reset structure parameters for ENET initialization */ +void enet_deinit(void); +/* configure the parameters which are usually less cared for initialization */ +void enet_initpara_config(enet_option_enum option, uint32_t para); +/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept); +/* reset all core internal registers located in CLK_TX and CLK_RX */ +ErrStatus enet_software_reset(void); +/* check receive frame valid and return frame size */ +uint32_t enet_rxframe_size_get(void); +/* initialize the dma tx/rx descriptors's parameters in chain mode */ +void enet_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma tx/rx descriptors's parameters in ring mode */ +void enet_descriptors_ring_init(enet_dmadirection_enum direction); +/* handle current received frame data to application buffer */ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize); +/* handle current received frame but without data copy to application buffer */ +#define ENET_NOCOPY_FRAME_RECEIVE() enet_frame_receive(NULL, 0U) +/* handle application buffer data to transmit it */ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); +/* handle current transmit frame but without data copy from application buffer */ +#define ENET_NOCOPY_FRAME_TRANSMIT(len) enet_frame_transmit(NULL, (len)) +/* configure the transmit IP frame checksum offload calculation and insertion */ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); +/* ENET Tx and Rx function enable (include MAC and DMA module) */ +void enet_enable(void); +/* ENET Tx and Rx function disable (include MAC and DMA module) */ +void enet_disable(void); +/* configure MAC address */ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); +/* get MAC address */ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]); + +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + +/* MAC function */ +/* ENET Tx function enable (include MAC and DMA module) */ +void enet_tx_enable(void); +/* ENET Tx function disable (include MAC and DMA module) */ +void enet_tx_disable(void); +/* ENET Rx function enable (include MAC and DMA module) */ +void enet_rx_enable(void); +/* ENET Rx function disable (include MAC and DMA module) */ +void enet_rx_disable(void); +/* put registers value into the application buffer */ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num); +/* enable the MAC address filter */ +void enet_address_filter_enable(enet_macaddress_enum mac_addr); +/* disable the MAC address filter */ +void enet_address_filter_disable(enet_macaddress_enum mac_addr); +/* configure the MAC address filter */ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type); +/* PHY interface configuration (configure SMI clock and reset PHY chip) */ +ErrStatus enet_phy_config(void); +/* write to/read from a PHY register */ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue); +/* enable the loopback function of phy chip */ +ErrStatus enet_phyloopback_enable(void); +/* disable the loopback function of phy chip */ +ErrStatus enet_phyloopback_disable(void); +/* enable ENET forward feature */ +void enet_forward_feature_enable(uint32_t feature); +/* disable ENET forward feature */ +void enet_forward_feature_disable(uint32_t feature); +/* enable ENET fliter feature */ +void enet_fliter_feature_enable(uint32_t feature); +/* disable ENET fliter feature */ +void enet_fliter_feature_disable(uint32_t feature); + +/* flow control function */ +/* generate the pause frame, ENET will send pause frame after enable transmit flow control */ +ErrStatus enet_pauseframe_generate(void); +/* configure the pause frame detect type */ +void enet_pauseframe_detect_config(uint32_t detect); +/* configure the pause frame parameters */ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold); +/* configure the threshold of the flow control(deactive and active threshold) */ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active); +/* enable ENET flow control feature */ +void enet_flowcontrol_feature_enable(uint32_t feature); +/* disable ENET flow control feature */ +void enet_flowcontrol_feature_disable(uint32_t feature); + +/* DMA function */ +/* get the dma transmit/receive process state */ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +/* poll the dma transmission/reception enable */ +void enet_dmaprocess_resume(enet_dmadirection_enum direction); +/* check and recover the Rx process */ +void enet_rxprocess_check_recovery(void); +/* flush the ENET transmit fifo, and wait until the flush operation completes */ +ErrStatus enet_txfifo_flush(void); +/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get); +/* get the Tx or Rx descriptor information */ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get); +/* get the number of missed frames during receiving */ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop); + +/* descriptor function */ +/* get the bit flag of ENET dma descriptor */ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag); +/* set the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); +/* clear the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will set */ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will not set */ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc); +/* drop current receive frame */ +void enet_rxframe_drop(void); +/* enable DMA feature */ +void enet_dma_feature_enable(uint32_t feature); +/* disable DMA feature */ +void enet_dma_feature_disable(uint32_t feature); + +/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr) enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr) enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr)) + +/* WUM function */ +/* wakeup frame filter register pointer reset */ +void enet_wum_filter_register_pointer_reset(void); +/* set the remote wakeup frame registers */ +void enet_wum_filter_config(uint32_t pdata[]); +/* enable wakeup management features */ +void enet_wum_feature_enable(uint32_t feature); +/* disable wakeup management features */ +void enet_wum_feature_disable(uint32_t feature); + +/* MSC function */ +/* reset the MAC statistics counters */ +void enet_msc_counters_reset(void); +/* enable the MAC statistics counter features */ +void enet_msc_feature_enable(uint32_t feature); +/* disable the MAC statistics counter features */ +void enet_msc_feature_disable(uint32_t feature); +/* get MAC statistics counter */ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); + +/* PTP function */ +/* change subsecond to nanosecond */ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond); +/* change nanosecond to subsecond */ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond); +/* enable the PTP features */ +void enet_ptp_feature_enable(uint32_t feature); +/* disable the PTP features */ +void enet_ptp_feature_disable(uint32_t feature); +/* configure the PTP timestamp function */ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func); +/* configure the PTP system time subsecond increment value */ +void enet_ptp_subsecond_increment_config(uint32_t subsecond); +/* adjusting the PTP clock frequency only in fine update mode */ +void enet_ptp_timestamp_addend_config(uint32_t add); +/* initializing or adding/subtracting to second of the PTP system time */ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond); +/* configure the PTP expected target time */ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond); +/* get the PTP current system time */ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct); +/* configure and start PTP timestamp counter */ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg); +/* adjust frequency in fine method by configure addend register */ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); +/* update system time in coarse method */ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); +/* set system time in fine method */ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +/* get the ptp flag status */ +FlagStatus enet_ptp_flag_get(uint32_t flag); + +/* internal function */ +/* reset the ENET initpara struct, call it before using enet_initpara_config() */ +void enet_initpara_reset(void); +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + +#endif /* GD32F10X_ENET_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h new file mode 100644 index 0000000000..eb0a1e5687 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h @@ -0,0 +1,431 @@ +/*! + \file gd32f10x_exmc.h + \brief definitions for the EXMC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_EXMC_H +#define GD32F10X_EXMC_H + +#include "gd32f10x.h" + +/* EXMC definitions */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ + +/* registers definitions */ +/* NOR/PSRAM */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register 0 */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register 0 */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register 0 */ + +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register 1 */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register 1 */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register 1 */ + +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register 2 */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register 2 */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register 2 */ + +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register 3 */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register 3 */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register 3 */ + +/* NAND/PC card */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register 1 */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register 1 */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register 1 */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register 1 */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register 1 */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register 2 */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register 2 */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register 2 */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register 2 */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register 2 */ + +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register 3 */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register 3 */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register 3 */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register 3 */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ + +/* bits definitions */ +/* NOR/PSRAM */ +/* EXMC_SNCTLx,x=0..3 */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write */ + +/* EXMC_SNTCFGx,x=0..3 */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_SNWTCFGx,x=0..3 */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNWTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNWTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* NAND/PC card */ +/* EXMC_NPCTLx,x=1..3 */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ + +/* EXMC_NPINTENx,x=1..3 */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ + +/* EXMC_NPCTCFGx,x=1..3 */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ + +/* EXMC_NPATCFGx,x=1..3 */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ + +/* EXMC_PIOTCFG3 */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ + +/* EXMC_NECCx,x=1,2 */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ + +/* constants definitions */ +/* EXMC NOR/SRAM timing initialize struct */ +typedef struct +{ + uint32_t asyn_access_mode; /*!< asynchronous access mode */ + uint32_t syn_data_latency; /*!< configure the data latency */ + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ + uint32_t bus_latency; /*!< configure the bus latency */ + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ +}exmc_norsram_timing_parameter_struct; + +/* EXMC NOR/SRAM initialize struct */ +typedef struct +{ + uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ + uint32_t extended_mode; /*!< enable or disable the extended mode */ + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ + uint32_t memory_write; /*!< enable or disable the write operation */ + uint32_t nwait_config; /*!< NWAIT signal configuration */ + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ + uint32_t burst_mode; /*!< enable or disable the burst mode */ + uint32_t databus_width; /*!< specifies the databus width of external memory */ + uint32_t memory_type; /*!< specifies the type of external memory */ + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extended mode is not used or the timing + parameters for read if the extended mode is used */ + exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extended mode is used */ +}exmc_norsram_parameter_struct; + +/* EXMC NAND/PC card timing initialize struct */ +typedef struct +{ + uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ + uint32_t waittime; /*!< configure the minimum wait time */ + uint32_t setuptime; /*!< configure the address setup time */ +}exmc_nand_pccard_timing_parameter_struct; + +/* EXMC NAND initialize struct */ +typedef struct +{ + uint32_t nand_bank; /*!< select the bank of NAND */ + uint32_t ecc_size; /*!< the page size for the ECC calculation */ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ + uint32_t databus_width; /*!< the NAND flash databus width */ + uint32_t wait_feature; /*!< enables or disables the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ +}exmc_nand_parameter_struct; + +/* EXMC PC card initialize struct */ +typedef struct +{ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t wait_feature; /*!< enables or disables the Wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO space */ +}exmc_pccard_parameter_struct;; + +/* EXMC register address */ +#define EXMC_SNCTL(region) REG32(EXMC + 0x08U * (region)) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG(region) REG32(EXMC + 0x04U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG(region) REG32(EXMC + 0x104U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U * (bank)) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U * (bank)) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U * (bank)) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U * (bank)) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U * (bank)) /*!< EXMC NAND ECC register */ + +/* NOR bank memory data bus width */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width 16 bits */ + +/* NOR bank memory type */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ + +/* asynchronous access mode */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ + +/* data latency for NOR flash */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency 17 EXMC_CLK */ + +/* synchronous clock divide ratio */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_DISABLE SNTCFG_CKDIV(0) /*!< EXMC_CLK disable */ +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ + +/* ECC size */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* 8192 bytes */ + +/* ALE to RE delay */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ + +/* CLE to RE delay */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ + +/* NAND bank memory data bus width */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width 16 bits */ + +/* EXMC NOR/SRAM bank region definition */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ + +/* EXMC NOR/SRAM write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE ((uint32_t)0x00080000U) /*!< synchronous write mode */ + +/* EXMC NWAIT signal configuration */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING ((uint32_t)0x00000800U) /*!< NWAIT signal is active during wait state */ + +/* EXMC NWAIT signal polarity configuration */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH ((uint32_t)0x00000200U) /*!< high level is active of NWAIT */ + +/* EXMC NAND/PC card bank definition */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ + +/* EXMC flag bits */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ + +/* EXMC interrupt flag bits */ +#define EXMC_NAND_PCCARD_INT_RISE EXMC_NPINTEN_INTREN /*!< interrupt rising edge detection enable */ +#define EXMC_NAND_PCCARD_INT_LEVEL EXMC_NPINTEN_INTHEN /*!< interrupt high-level detection enable */ +#define EXMC_NAND_PCCARD_INT_FALL EXMC_NPINTEN_INTFEN /*!< interrupt falling edge detection enable */ + +/* function declarations */ +/* deinitialize EXMC NOR/SRAM region */ +void exmc_norsram_deinit(uint32_t norsram_region); +/* exmc_norsram_parameter_struct parameter initialize */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize EXMC NOR/SRAM region */ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* EXMC NOR/SRAM bank enable */ +void exmc_norsram_enable(uint32_t norsram_region); +/* EXMC NOR/SRAM bank disable */ +void exmc_norsram_disable(uint32_t norsram_region); + +/* deinitialize EXMC NAND bank */ +void exmc_nand_deinit(uint32_t nand_bank); +/* initialize EXMC NAND bank */ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* exmc_nand_init_struct parameter initialize */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* EXMC NAND bank enable */ +void exmc_nand_enable(uint32_t nand_bank); +/* EXMC NAND bank disable */ +void exmc_nand_disable(uint32_t nand_bank); +/* enable or disable the EXMC NAND ECC function */ +void exmc_nand_ecc_config(uint32_t nand_bank, ControlStatus newvalue); +/* get the EXMC ECC value */ +uint32_t exmc_ecc_get(uint32_t nand_bank); + +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* exmc_pccard_parameter_struct parameter initialize */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* EXMC PC card bank enable */ +void exmc_pccard_enable(void); +/* EXMC PC card bank disable */ +void exmc_pccard_disable(void); + +/* enable EXMC interrupt */ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source); +/* disable EXMC interrupt */ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source); +/* check EXMC flag is set or not */ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag); +/* clear EXMC flag */ +void exmc_flag_clear(uint32_t bank, uint32_t flag); +/* check EXMC flag is set or not */ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source); +/* clear EXMC flag */ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source); + +#endif /* GD32F10X_EXMC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h new file mode 100644 index 0000000000..d73a195a0b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h @@ -0,0 +1,257 @@ +/*! + \file gd32f10x_exti.h + \brief definitions for the EXTI + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_EXTI_H +#define GD32F10X_EXTI_H + +#include "gd32f10x.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ +#define EXTI_INTEN_INTEN19 BIT(19) /*!< interrupt from line 19 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ +#define EXTI_EVEN_EVEN19 BIT(19) /*!< event from line 19 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ +#define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ +#define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ +#define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum +{ + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ + EXTI_19 = BIT(19), /*!< EXTI line 19 */ +}exti_line_enum; + +/* external interrupt and event */ +typedef enum +{ + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +}exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum +{ + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH /*!< EXTI rising edge and falling edge trigger */ +}exti_trig_type_enum; + +/* function declarations */ +/* initialization, EXTI lines configuration functions */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* interrupt & flag functions */ +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32F10X_EXTI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h new file mode 100644 index 0000000000..d5b834ee0d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h @@ -0,0 +1,369 @@ +/*! + \file gd32f10x_fmc.h + \brief definitions for the FMC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_FMC_H +#define GD32F10X_FMC_H + +#include "gd32f10x.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0,2) /*!< wait state counter */ + +/* FMC_KEY0 */ +#define FMC_KEY0_KEY BITS(0,31) /*!< FMC_CTL0 unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0,31) /*!< option bytes unlock key bits */ + +/* FMC_STAT0 */ +#define FMC_STAT0_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT0_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT0_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT0_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL0 */ +#define FMC_CTL0_PG BIT(0) /*!< main flash program for bank0 command bit */ +#define FMC_CTL0_PER BIT(1) /*!< main flash page erase for bank0 command bit */ +#define FMC_CTL0_MER BIT(2) /*!< main flash mass erase for bank0 command bit */ +#define FMC_CTL0_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL0_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL0_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL0_LK BIT(7) /*!< FMC_CTL0 lock bit */ +#define FMC_CTL0_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL0_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR0 */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2,9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10,25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0,31) /*!< store WP of option bytes block after system reset */ + +/* FMC_KEY1 */ +#define FMC_KEY1_KEY BITS(0,31) /*!< FMC_CTL1 unlock key bits */ + +/* FMC_STAT1 */ +#define FMC_STAT1_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT1_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT1_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT1_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL1 */ +#define FMC_CTL1_PG BIT(0) /*!< main flash program for bank1 command bit */ +#define FMC_CTL1_PER BIT(1) /*!< main flash page erase for bank1 command bit */ +#define FMC_CTL1_MER BIT(2) /*!< main flash mass erase for bank1 command bit */ +#define FMC_CTL1_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL1_LK BIT(7) /*!< FMC_CTL1 lock bit */ +#define FMC_CTL1_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR1 */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< flash erase/program command address bits */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0,31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum +{ + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +}fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum +{ + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ +}fmc_int_enum; + +/* FMC flags */ +typedef enum +{ + FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ + FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ + FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ + FMC_FLAG_BANK0_END = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U), /*!< FMC bank0 end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ + FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ + FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ + FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ +}fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum +{ + FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ + FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ +}fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* unlock the FMC bank0 operation */ +void fmc_bank0_unlock(void); +/* unlock the FMC bank1 operation */ +void fmc_bank1_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* lock the bank0 FMC operation */ +void fmc_bank0_lock(void); +/* lock the bank1 FMC operation */ +void fmc_bank1_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC erase whole bank0 */ +fmc_state_enum fmc_bank0_erase(void); +/* FMC erase whole bank1 */ +fmc_state_enum fmc_bank1_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the option byte */ +fmc_state_enum ob_erase(void); +/* enable write protect */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure the option byte security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* write the FMC option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program option bytes data */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get the FMC option byte user */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get option byte security protection code value */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); +/* check FMC bank0 ready or not */ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + +#endif /* GD32F10X_FMC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h new file mode 100644 index 0000000000..d17c3691ee --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h @@ -0,0 +1,107 @@ +/*! + \file gd32f10x_fwdgt.h + \brief definitions for the FWDGT + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_FWDGT_H +#define GD32F10X_FWDGT_H + +#include "gd32f10x.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE /*!< FWDGT base address */ + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x04U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x08U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0,15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0,2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0,11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32F10X_FWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h new file mode 100644 index 0000000000..eeafc41012 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h @@ -0,0 +1,498 @@ +/*! + \file gd32f10x_gpio.h + \brief definitions for the GPIO + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_GPIO_H +#define GD32F10x_GPIO_H + +#include "gd32f10x.h" + +/* GPIOx(x=A,B,C,D,E,F,G) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) +#define GPIOF (GPIO_BASE + 0x00001400U) +#define GPIOG (GPIO_BASE + 0x00001800U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ + +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8,9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10,11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12,13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14,15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16,17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18,19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20,21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22,23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24,25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26,27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28,29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8,9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10,11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12,13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14,15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16,17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18,19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20,21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22,23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24,25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26,27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28,29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0,3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4,6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#ifdef GD32F10X_CL +/* memory map and bit definitions for GD32F10X_CL devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN0_REMAP BITS(13,14) /*!< CAN0 remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER3 channel3 internal remapping */ +#define AFIO_PCF0_ENET_REMAP BIT(21) /*!< ethernet MAC I/O remapping */ +#define AFIO_PCF0_CAN1_REMAP BIT(22) /*!< CAN1 remapping */ +#define AFIO_PCF0_ENET_PHY_SEL BIT(23) /*!< ethernet MII or RMII PHY selection */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1ITI1_REMAP BIT(29) /*!< TIMER1 internal trigger 1 remapping */ +#define AFIO_PCF0_PTP_PPS_REMAP BIT(30) /*!< ethernet PTP PPS remapping */ + +#else +/* memory map and bit definitions for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN_REMAP BITS(13,14) /*!< CAN remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_REMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ADC0_ETRGINS_REMAP BIT(17) /*!< ADC 0 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC0_ETRGREG_REMAP BIT(18) /*!< ADC 0 external trigger regular conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGINS_REMAP BIT(19) /*!< ADC 1 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGREG_REMAP BIT(20) /*!< ADC 1 external trigger regular conversion remapping */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#endif /* GD32F10X_CL */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0,3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4,7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8,11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12,15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0,3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4,7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8,11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12,15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0,3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4,7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8,11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12,15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0,3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4,7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8,11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12,15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_TIMER8_REMAP BIT(5) /*!< TIMER8 remapping */ +#define AFIO_PCF1_TIMER9_REMAP BIT(6) /*!< TIMER9 remapping */ +#define AFIO_PCF1_TIMER10_REMAP BIT(7) /*!< TIMER10 remapping */ +#define AFIO_PCF1_TIMER12_REMAP BIT(8) /*!< TIMER12 remapping */ +#define AFIO_PCF1_TIMER13_REMAP BIT(9) /*!< TIMER13 remapping */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ +#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05U) /*!< output port source F */ +#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06U) /*!< output port source G */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ + +/* GPIO remap definitions */ +#define GPIO_SPI0_REMAP ((uint32_t)0x00000001U) /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP ((uint32_t)0x00000002U) /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP ((uint32_t)0x00000004U) /*!< USART0 remapping */ +#define GPIO_USART1_REMAP ((uint32_t)0x00000008U) /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140010U) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140030U) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160040U) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x001600C0U) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180100U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180200U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180300U) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0800U) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0C00U) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP ((uint32_t)0x00001000U) /*!< TIMER3 remapping */ +#define GPIO_PD01_REMAP ((uint32_t)0x00008000U) /*!< PD01 remapping */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define GPIO_CAN_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN partial remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_CAN_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN full remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#endif /* GD32F10X_MD||GD32F10X_HD||GD32F10X_XD */ +#if (defined(GD32F10X_CL) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define GPIO_SPI2_REMAP ((uint32_t)0x00201100U) /*!< SPI2 remapping(only for GD32F10X_CL devices) */ +#endif /* GD32F10X_CL||GD32F10X_HD */ +#if (defined(GD32F10X_CL) || defined(GD32F10X_HD)) +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200001U) /*!< TIMER4 channel3 internal remapping(only for GD32F10X_CL devices and GD32F10X_HD devices) */ +#endif /* GD32F10X_CL||GD32F10X_HD */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define GPIO_ADC0_ETRGINS_REMAP ((uint32_t)0x00200002U) /*!< ADC0 external trigger inserted conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_ADC0_ETRGREG_REMAP ((uint32_t)0x00200004U) /*!< ADC0 external trigger regular conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_ADC1_ETRGINS_REMAP ((uint32_t)0x00200008U) /*!< ADC1 external trigger inserted conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_ADC1_ETRGREG_REMAP ((uint32_t)0x00200010U) /*!< ADC1 external trigger regular conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#endif /* GD32F10X_MD||GD32F10X_HD||GD32F10X_XD */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300100U) /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */ +#define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300200U) /*!< JTAG-DP disabled and SW-DP enabled */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300400U) /*!< JTAG-DP disabled and SW-DP disabled */ +#ifdef GD32F10X_CL +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN0 partial remapping(only for GD32F10X_CL devices) */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN0 full remapping(only for GD32F10X_CL devices) */ +#define GPIO_ENET_REMAP ((uint32_t)0x00200020U) /*!< ENET remapping(only for GD32F10X_CL devices) */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200040U) /*!< CAN1 remapping(only for GD32F10X_CL devices) */ +#define GPIO_TIMER1ITI1_REMAP ((uint32_t)0x00202000U) /*!< TIMER1 internal trigger 1 remapping(only for GD32F10X_CL devices) */ +#define GPIO_PTP_PPS_REMAP ((uint32_t)0x00204000U) /*!< ethernet PTP PPS remapping(only for GD32F10X_CL devices) */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define GPIO_TIMER8_REMAP ((uint32_t)0x80000020U) /*!< TIMER8 remapping */ +#define GPIO_TIMER9_REMAP ((uint32_t)0x80000040U) /*!< TIMER9 remapping */ +#define GPIO_TIMER10_REMAP ((uint32_t)0x80000080U) /*!< TIMER10 remapping */ +#define GPIO_TIMER12_REMAP ((uint32_t)0x80000100U) /*!< TIMER12 remapping */ +#define GPIO_TIMER13_REMAP ((uint32_t)0x80000200U) /*!< TIMER13 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000400U) /*!< EXMC_NADV connect/disconnect */ +#endif /* GD32F10X_XD */ + +#ifdef GD32F10X_CL +/* ethernet MII or RMII PHY selection */ +#define GPIO_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< configure ethernet MAC for connection with an MII PHY */ +#define GPIO_ENET_PHY_RMII AFIO_PCF0_ENET_PHY_SEL /*!< configure ethernet MAC for connection with an RMII PHY */ +#endif /* GD32F10X_CL */ + +/* function declarations */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph,uint32_t mode,uint32_t speed,uint32_t pin); + +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); + +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue); + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); + +#ifdef GD32F10X_CL +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t gpio_enetsel); +#endif /* GD32F10X_CL */ + + +#endif /* GD32F10x_GPIO_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h new file mode 100644 index 0000000000..44781cdd6e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h @@ -0,0 +1,347 @@ +/*! + \file gd32f10x_i2c.h + \brief definitions for the I2C + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-04-16, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_I2C_H +#define GD32F10X_I2C_H + +#include "gd32f10x.h" + +/* I2Cx(x=0,1) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ + +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_PECV BITS(8,15) /*!< packet error checking value */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0,5) /*!< maximum rise time in fast/standard mode (Master mode) */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U), /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +}i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< SCL stretching is enabled */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< SCL stretching is disabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP is enabled */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP is disabled */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); + +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32E10X_I2C_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h new file mode 100644 index 0000000000..38e3110998 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h @@ -0,0 +1,94 @@ +/*! + \file gd32f10x_misc.h + \brief definitions for the MISC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_MISC_H +#define GD32F10X_MISC_H + +#include "gd32f10x.h" + +/* constants definitions */ +/* set the RAM and FLASH base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ + +/* set the NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) + +/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) + +/* priority group - define the pre-emption priority and the subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ + +/* choose the method to enter or exit the lowpower mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ + +#define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT +#define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP +#define SCB_LPM_WAKE_BY_ALL_INT SCB_SCR_SEVONPEND + +/* choose the systick clock source */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */ +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ + +/* function declarations */ +/* set the priority group */ +void nvic_priority_group_set(uint32_t nvic_prigroup); + +/* enable NVIC request */ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); +/* disable NVIC request */ +void nvic_irq_disable(uint8_t nvic_irq); + +/* set the NVIC vector table base address */ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); + +/* set the state of the low power mode */ +void system_lowpower_set(uint8_t lowpower_mode); +/* reset the state of the low power mode */ +void system_lowpower_reset(uint8_t lowpower_mode); + +/* set the systick clock source */ +void systick_clksource_set(uint32_t systick_clksource); + +#endif /* GD32F10X_MISC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h new file mode 100644 index 0000000000..edd53a69c3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h @@ -0,0 +1,128 @@ +/*! + \file gd32f10x_pmu.h + \brief definitions for the PMU + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_PMU_H +#define GD32F10X_PMU_H + +#include "gd32f10x.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5,7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval) << 5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.5V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 2.8V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 2.9V */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable write access to the registers in backup domain */ +void pmu_backup_write_enable(void); +/* disable write access to the registers in backup domain */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); + +#endif /* GD32F10X_PMU_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h new file mode 100644 index 0000000000..29444f3e80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h @@ -0,0 +1,923 @@ +/*! + \file gd32f10x_rcu.h + \brief definitions for the RCU + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_RCU_H +#define GD32F10X_RCU_H + +#include "gd32f10x.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#elif defined(GD32F10X_CL) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHBRST REG32(RCU + 0x28U) /*!< AHB reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* bits definitions */ +/* RCU_CTL */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#elif defined(GD32F10X_CL) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_CFG0 */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0 BIT(17) /*!< PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBDPSC BITS(22,23) /*!< USBD clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,26) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_PLLMF_4 BIT(27) /*!< bit 4 of PLLMF */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#elif defined(GD32F10X_CL) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_INT */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K Stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL Stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M Stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL Stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#elif defined(GD32F10X_CL) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ +#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ +#ifndef GD32F10X_CL +#define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ +#endif /* GD32F10X_XD */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ +#ifdef GD32F10X_XD +#define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ +#endif /* GD32F10X_XD */ +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_APB1RST_USBDRST BIT(23) /*!< USBD reset */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#ifdef GD32F10X_CL +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#endif /* GD32F10X_CL */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHBEN */ +#define RCU_AHBEN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHBEN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHBEN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHBEN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHBEN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHBEN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_AHBEN_SDIOEN BIT(10) /*!< SDIO clock enable */ +#elif defined(GD32F10X_CL) +#define RCU_AHBEN_USBFSEN BIT(12) /*!< USBFS clock enable */ +#define RCU_AHBEN_ENETEN BIT(14) /*!< ENET clock enable */ +#define RCU_AHBEN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ +#define RCU_AHBEN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ +#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ +#ifndef GD32F10X_CL +#define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ +#endif /* GD32F10X_XD */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#ifdef GD32F10X_XD +#define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ +#endif /* GD32F10X_XD */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_APB1EN_USBDEN BIT(23) /*!< USBD clock enable */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#ifdef GD32F10X_CL +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#endif /* GD32F10X_CL */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +#ifdef GD32F10X_CL +/* RCU_AHBRST */ +#define RCU_AHBRST_USBFSRST BIT(12) /*!< USBFS reset */ +#define RCU_AHBRST_ENETRST BIT(14) /*!< ENET reset */ +#endif /* GD32F10X_CL */ + +#if defined(GD32F10X_CL) +/* RCU_CFG1 */ +#define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ +#endif /* GD32F10X_CL */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHBEN_REG_OFFSET 0x14U /*!< AHB enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ + +/* peripherals reset */ +#define AHBRST_REG_OFFSET 0x28U /*!< AHB reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source/clock register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< clock interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< clock configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< clock configuration register 1 offset */ + +/* peripheral clock enable */ +typedef enum +{ + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U), /*!< EXMC clock */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_SDIO = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 10U), /*!< SDIO clock */ +#elif defined(GD32F10X_CL) + RCU_USBFS = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U), /*!< USBFS clock */ + RCU_ENET = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 14U), /*!< ENET clock */ + RCU_ENETTX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 15U), /*!< ENETTX clock */ + RCU_ENETRX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 16U), /*!< ENETRX clock */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ +#if defined(GD32F10X_XD) + RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ + RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ +#endif /* GD32F10X_XD */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_USBD = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< USBD clock */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ +#ifdef GD32F10X_CL + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ +#endif /* GD32F10X_CL */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ + RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ +#ifndef GD32F10X_CL + RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD + RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ + RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ + RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ +#endif /* GD32F10X_XD */ +}rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum +{ + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U), /*!< FMC clock */ +}rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum +{ + /* AHB peripherals */ +#ifdef GD32F10X_CL + RCU_USBFSRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 14U), /*!< ENET clock reset */ +#endif /* GD32F10X_CL */ + + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ +#ifdef GD32F10X_XD + RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ + RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ +#endif /* GD32F10X_XD */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_USBDRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< USBD clock reset */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ +#ifdef GD32F10X_CL + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ +#endif /* GD32F10X_CL */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ + RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ +#ifndef GD32F10X_CL + RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD + RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ + RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ + RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ +#endif /* GD32F10X_XD */ +}rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum +{ + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ +#ifdef GD32F10X_CL + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ +#endif /* GD32F10X_CL */ + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +}rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ +#ifdef GD32F10X_CL + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ +#endif /* GD32F10X_CL */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ +}rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ +#ifdef GD32F10X_CL + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ +#endif /* GD32F10X_CL */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ +}rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum +{ + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ +#ifdef GD32F10X_CL + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ +#endif /* GD32F10X_CL */ +}rcu_int_enum; + +/* oscillator types */ +typedef enum +{ + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ +#ifdef GD32F10X_CL + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ +#endif /* GD32F10X_CL */ +}rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum +{ + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +}rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source select */ +#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler select */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL RCU_CFG0_PLLSEL /*!< HXTAL clock selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_PLL_MUL15 CFG0_PLLMF(13) /*!< PLL source clock multiply by 15 */ +#elif defined(GD32F10X_CL) +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ + +/* USBD/USBFS prescaler select */ +#define CFG0_USBPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBPSC(0) /*!< USBD/USBFS prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBPSC(1) /*!< USBD/USBFS prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBPSC(2) /*!< USBD/USBFS prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBPSC(3) /*!< USBD/USBFS prescaler select CK_PLL/2 */ + +/* CKOUT0 clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#ifdef GD32F10X_CL +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ +#endif /* GD32F10X_CL */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV_128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock not divided */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock not divided */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ + +#ifdef GD32F10X_CL +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ +#endif /* GD32F10X_CL */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_2 DSV_DSLPVS(0) /*!< core voltage is 1.2V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_1 DSV_DSLPVS(1) /*!< core voltage is 1.1V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(2) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(3) /*!< core voltage is 0.9V in deep-sleep mode */ + +/* function declarations */ +/* initialization, peripheral clock enable/disable functions */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* clock configuration functions */ +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src); +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_div); +#elif defined(GD32F10X_CL) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* peripheral clock configuration functions */ +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBD/USBFS prescaler factor */ +void rcu_usb_clock_config(uint32_t usb_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); +#ifdef GD32F10X_CL +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); +#endif /* GD32F10X_CL */ + +/* interrupt & flag functions */ +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum stab_int); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum stab_int); + +/* oscillator configuration functions */ +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval); +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32F10X_RCU_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h new file mode 100644 index 0000000000..7a7e8d65a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h @@ -0,0 +1,151 @@ +/*! + \file gd32f10x_rtc.h + \brief definitions for the RTC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_RTC_H +#define GD32F10X_RTC_H + +#include "gd32f10x.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSCH */ +#define RTC_PSCH_PSC BITS(0,3) /*!< prescaler high value */ + +/* RTC_PSCL */ +#define RTC_PSCL_PSC BITS(0,15) /*!< prescaler low value */ + +/* RTC_DIVH */ +#define RTC_DIVH_DIV BITS(0,3) /*!< divider high value */ + +/* RTC_DIVL */ +#define RTC_DIVL_DIV BITS(0,15) /*!< divider low value */ + +/* RTC_CNTH */ +#define RTC_CNTH_CNT BITS(0,15) /*!< counter high value */ + +/* RTC_CNTL */ +#define RTC_CNTL_CNT BITS(0,15) /*!< counter low value */ + +/* RTC_ALRMH */ +#define RTC_ALRMH_ALRM BITS(0,15) /*!< alarm high value */ + +/* RTC_ALRML */ +#define RTC_ALRML_ALRM BITS(0,15) /*!< alarm low value */ + +/* constants definitions */ +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC interrupt flag definitions */ +#define RTC_INT_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_INT_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_INT_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* initialization functions */ +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); + +/* operation functions */ +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* flag & interrupt functions */ +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); +/* get RTC interrupt flag status */ +FlagStatus rtc_interrupt_flag_get(uint32_t flag); +/* clear RTC interrupt flag status */ +void rtc_interrupt_flag_clear(uint32_t flag); +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +#endif /* GD32F10X_RTC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h new file mode 100644 index 0000000000..4cb178ad70 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h @@ -0,0 +1,429 @@ +/*! + \file gd32f10x_sdio.h + \brief definitions for the SDIO + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_SDIO_H +#define GD32F10X_SDIO_H + +#include "gd32f10x.h" + +/* SDIO definitions */ +#define SDIO SDIO_BASE + +/* registers definitions */ +#define SDIO_PWRCTL REG32(SDIO + 0x00U) /*!< SDIO power control register */ +#define SDIO_CLKCTL REG32(SDIO + 0x04U) /*!< SDIO clock control register */ +#define SDIO_CMDAGMT REG32(SDIO + 0x08U) /*!< SDIO command argument register */ +#define SDIO_CMDCTL REG32(SDIO + 0x0CU) /*!< SDIO command control register */ +#define SDIO_RSPCMDIDX REG32(SDIO + 0x10U) /*!< SDIO command index response register */ +#define SDIO_RESP0 REG32(SDIO + 0x14U) /*!< SDIO response register 0 */ +#define SDIO_RESP1 REG32(SDIO + 0x18U) /*!< SDIO response register 1 */ +#define SDIO_RESP2 REG32(SDIO + 0x1CU) /*!< SDIO response register 2 */ +#define SDIO_RESP3 REG32(SDIO + 0x20U) /*!< SDIO response register 3 */ +#define SDIO_DATATO REG32(SDIO + 0x24U) /*!< SDIO data timeout register */ +#define SDIO_DATALEN REG32(SDIO + 0x28U) /*!< SDIO data length register */ +#define SDIO_DATACTL REG32(SDIO + 0x2CU) /*!< SDIO data control register */ +#define SDIO_DATACNT REG32(SDIO + 0x30U) /*!< SDIO data counter register */ +#define SDIO_STAT REG32(SDIO + 0x34U) /*!< SDIO status register */ +#define SDIO_INTC REG32(SDIO + 0x38U) /*!< SDIO interrupt clear register */ +#define SDIO_INTEN REG32(SDIO + 0x3CU) /*!< SDIO interrupt enable register */ +#define SDIO_FIFOCNT REG32(SDIO + 0x48U) /*!< SDIO FIFO counter register */ +#define SDIO_FIFO REG32(SDIO + 0x80U) /*!< SDIO FIFO data register */ + +/* bits definitions */ +/* SDIO_PWRCTL */ +#define SDIO_PWRCTL_PWRCTL BITS(0,1) /*!< SDIO power control bits */ + +/* SDIO_CLKCTL */ +#define SDIO_CLKCTL_DIV BITS(0,7) /*!< clock division */ +#define SDIO_CLKCTL_CLKEN BIT(8) /*!< SDIO_CLK clock output enable bit */ +#define SDIO_CLKCTL_CLKPWRSAV BIT(9) /*!< SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLKCTL_CLKBYP BIT(10) /*!< clock bypass enable bit */ +#define SDIO_CLKCTL_BUSMODE BITS(11,12) /*!< SDIO card bus mode control bit */ +#define SDIO_CLKCTL_CLKEDGE BIT(13) /*!< SDIO_CLK clock edge selection bit */ +#define SDIO_CLKCTL_HWCLKEN BIT(14) /*!< hardware clock control enable bit */ + +/* SDIO_CMDAGMT */ +#define SDIO_CMDAGMT_CMDAGMT BITS(0,31) /*!< SDIO card command argument */ + +/* SDIO_CMDCTL */ +#define SDIO_CMDCTL_CMDIDX BITS(0,5) /*!< command index */ +#define SDIO_CMDCTL_CMDRESP BITS(6,7) /*!< command response type bits */ +#define SDIO_CMDCTL_INTWAIT BIT(8) /*!< interrupt wait instead of timeout */ +#define SDIO_CMDCTL_WAITDEND BIT(9) /*!< wait for ends of data transfer */ +#define SDIO_CMDCTL_CSMEN BIT(10) /*!< command state machine(CSM) enable bit */ +#define SDIO_CMDCTL_SUSPEND BIT(11) /*!< SD I/O suspend command(SD I/O only) */ +#define SDIO_CMDCTL_ENCMDC BIT(12) /*!< CMD completion signal enabled (CE-ATA only) */ +#define SDIO_CMDCTL_NINTEN BIT(13) /*!< no CE-ATA interrupt (CE-ATA only) */ +#define SDIO_CMDCTL_ATAEN BIT(14) /*!< CE-ATA command enable(CE-ATA only) */ + +/* SDIO_DATATO */ +#define SDIO_DATATO_DATATO BITS(0,31) /*!< data timeout period */ + +/* SDIO_DATALEN */ +#define SDIO_DATALEN_DATALEN BITS(0,24) /*!< data transfer length */ + +/* SDIO_DATACTL */ +#define SDIO_DATACTL_DATAEN BIT(0) /*!< data transfer enabled bit */ +#define SDIO_DATACTL_DATADIR BIT(1) /*!< data transfer direction */ +#define SDIO_DATACTL_TRANSMOD BIT(2) /*!< data transfer mode */ +#define SDIO_DATACTL_DMAEN BIT(3) /*!< DMA enable bit */ +#define SDIO_DATACTL_BLKSZ BITS(4,7) /*!< data block size */ +#define SDIO_DATACTL_RWEN BIT(8) /*!< read wait mode enabled(SD I/O only) */ +#define SDIO_DATACTL_RWSTOP BIT(9) /*!< read wait stop(SD I/O only) */ +#define SDIO_DATACTL_RWTYPE BIT(10) /*!< read wait type(SD I/O only) */ +#define SDIO_DATACTL_IOEN BIT(11) /*!< SD I/O specific function enable(SD I/O only) */ + +/* SDIO_STAT */ +#define SDIO_STAT_CCRCERR BIT(0) /*!< command response received (CRC check failed) */ +#define SDIO_STAT_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) */ +#define SDIO_STAT_CMDTMOUT BIT(2) /*!< command response timeout */ +#define SDIO_STAT_DTTMOUT BIT(3) /*!< data timeout */ +#define SDIO_STAT_TXURE BIT(4) /*!< transmit FIFO underrun error occurs */ +#define SDIO_STAT_RXORE BIT(5) /*!< received FIFO overrun error occurs */ +#define SDIO_STAT_CMDRECV BIT(6) /*!< command response received (CRC check passed) */ +#define SDIO_STAT_CMDSEND BIT(7) /*!< command sent (no response required) */ +#define SDIO_STAT_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) */ +#define SDIO_STAT_STBITE BIT(9) /*!< start bit error in the bus */ +#define SDIO_STAT_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) */ +#define SDIO_STAT_CMDRUN BIT(11) /*!< command transmission in progress */ +#define SDIO_STAT_TXRUN BIT(12) /*!< data transmission in progress */ +#define SDIO_STAT_RXRUN BIT(13) /*!< data reception in progress */ +#define SDIO_STAT_TFH BIT(14) /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */ +#define SDIO_STAT_RFH BIT(15) /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */ +#define SDIO_STAT_TFF BIT(16) /*!< transmit FIFO is full */ +#define SDIO_STAT_RFF BIT(17) /*!< receive FIFO is full */ +#define SDIO_STAT_TFE BIT(18) /*!< transmit FIFO is empty */ +#define SDIO_STAT_RFE BIT(19) /*!< receive FIFO is empty */ +#define SDIO_STAT_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO */ +#define SDIO_STAT_RXDTVAL BIT(21) /*!< data is valid in receive FIFO */ +#define SDIO_STAT_SDIOINT BIT(22) /*!< SD I/O interrupt received */ +#define SDIO_STAT_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) */ + +/* SDIO_INTC */ +#define SDIO_INTC_CCRCERRC BIT(0) /*!< CCRCERR flag clear bit */ +#define SDIO_INTC_DTCRCERRC BIT(1) /*!< DTCRCERR flag clear bit */ +#define SDIO_INTC_CMDTMOUTC BIT(2) /*!< CMDTMOUT flag clear bit */ +#define SDIO_INTC_DTTMOUTC BIT(3) /*!< DTTMOUT flag clear bit */ +#define SDIO_INTC_TXUREC BIT(4) /*!< TXURE flag clear bit */ +#define SDIO_INTC_RXOREC BIT(5) /*!< RXORE flag clear bit */ +#define SDIO_INTC_CMDRECVC BIT(6) /*!< CMDRECV flag clear bit */ +#define SDIO_INTC_CMDSENDC BIT(7) /*!< CMDSEND flag clear bit */ +#define SDIO_INTC_DTENDC BIT(8) /*!< DTEND flag clear bit */ +#define SDIO_INTC_STBITEC BIT(9) /*!< STBITE flag clear bit */ +#define SDIO_INTC_DTBLKENDC BIT(10) /*!< DTBLKEND flag clear bit */ +#define SDIO_INTC_SDIOINTC BIT(22) /*!< SDIOINT flag clear bit */ +#define SDIO_INTC_ATAENDC BIT(23) /*!< ATAEND flag clear bit */ + +/* SDIO_INTEN */ +#define SDIO_INTEN_CCRCERRIE BIT(0) /*!< command response CRC fail interrupt enable */ +#define SDIO_INTEN_DTCRCERRIE BIT(1) /*!< data CRC fail interrupt enable */ +#define SDIO_INTEN_CMDTMOUTIE BIT(2) /*!< command response timeout interrupt enable */ +#define SDIO_INTEN_DTTMOUTIE BIT(3) /*!< data timeout interrupt enable */ +#define SDIO_INTEN_TXUREIE BIT(4) /*!< transmit FIFO underrun error interrupt enable */ +#define SDIO_INTEN_RXOREIE BIT(5) /*!< received FIFO overrun error interrupt enable */ +#define SDIO_INTEN_CMDRECVIE BIT(6) /*!< command response received interrupt enable */ +#define SDIO_INTEN_CMDSENDIE BIT(7) /*!< command sent interrupt enable */ +#define SDIO_INTEN_DTENDIE BIT(8) /*!< data end interrupt enable */ +#define SDIO_INTEN_STBITEIE BIT(9) /*!< start bit error interrupt enable */ +#define SDIO_INTEN_DTBLKENDIE BIT(10) /*!< data block end interrupt enable */ +#define SDIO_INTEN_CMDRUNIE BIT(11) /*!< command transmission interrupt enable */ +#define SDIO_INTEN_TXRUNIE BIT(12) /*!< data transmission interrupt enable */ +#define SDIO_INTEN_RXRUNIE BIT(13) /*!< data reception interrupt enable */ +#define SDIO_INTEN_TFHIE BIT(14) /*!< transmit FIFO half empty interrupt enable */ +#define SDIO_INTEN_RFHIE BIT(15) /*!< receive FIFO half full interrupt enable */ +#define SDIO_INTEN_TFFIE BIT(16) /*!< transmit FIFO full interrupt enable */ +#define SDIO_INTEN_RFFIE BIT(17) /*!< receive FIFO full interrupt enable */ +#define SDIO_INTEN_TFEIE BIT(18) /*!< transmit FIFO empty interrupt enable */ +#define SDIO_INTEN_RFEIE BIT(19) /*!< receive FIFO empty interrupt enable */ +#define SDIO_INTEN_TXDTVALIE BIT(20) /*!< data valid in transmit FIFO interrupt enable */ +#define SDIO_INTEN_RXDTVALIE BIT(21) /*!< data valid in receive FIFO interrupt enable */ +#define SDIO_INTEN_SDIOINTIE BIT(22) /*!< SD I/O interrupt received interrupt enable */ +#define SDIO_INTEN_ATAENDIE BIT(23) /*!< CE-ATA command completion signal received interrupt enable */ + +/* SDIO_FIFO */ +#define SDIO_FIFO_FIFODT BITS(0,31) /*!< receive FIFO data or transmit FIFO data */ + +/* constants definitions */ +/* SDIO flags */ +#define SDIO_FLAG_CCRCERR BIT(0) /*!< command response received (CRC check failed) flag */ +#define SDIO_FLAG_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) flag */ +#define SDIO_FLAG_CMDTMOUT BIT(2) /*!< command response timeout flag */ +#define SDIO_FLAG_DTTMOUT BIT(3) /*!< data timeout flag */ +#define SDIO_FLAG_TXURE BIT(4) /*!< transmit FIFO underrun error occurs flag */ +#define SDIO_FLAG_RXORE BIT(5) /*!< received FIFO overrun error occurs flag */ +#define SDIO_FLAG_CMDRECV BIT(6) /*!< command response received (CRC check passed) flag */ +#define SDIO_FLAG_CMDSEND BIT(7) /*!< command sent (no response required) flag */ +#define SDIO_FLAG_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) flag */ +#define SDIO_FLAG_STBITE BIT(9) /*!< start bit error in the bus flag */ +#define SDIO_FLAG_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) flag */ +#define SDIO_FLAG_CMDRUN BIT(11) /*!< command transmission in progress flag */ +#define SDIO_FLAG_TXRUN BIT(12) /*!< data transmission in progress flag */ +#define SDIO_FLAG_RXRUN BIT(13) /*!< data reception in progress flag */ +#define SDIO_FLAG_TFH BIT(14) /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */ +#define SDIO_FLAG_RFH BIT(15) /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */ +#define SDIO_FLAG_TFF BIT(16) /*!< transmit FIFO is full flag */ +#define SDIO_FLAG_RFF BIT(17) /*!< receive FIFO is full flag */ +#define SDIO_FLAG_TFE BIT(18) /*!< transmit FIFO is empty flag */ +#define SDIO_FLAG_RFE BIT(19) /*!< receive FIFO is empty flag */ +#define SDIO_FLAG_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO flag */ +#define SDIO_FLAG_RXDTVAL BIT(21) /*!< data is valid in receive FIFO flag */ +#define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ +#define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ + +/* SDIO interrupt enable or disable */ +#define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO power control */ +#define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ +#define SDIO_POWER_ON PWRCTL_PWRCTL(3) /*!< SDIO power on */ + +/* SDIO card bus mode control */ +#define CLKCTL_BUSMODE(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) +#define SDIO_BUSMODE_1BIT CLKCTL_BUSMODE(0) /*!< 1-bit SDIO card bus mode */ +#define SDIO_BUSMODE_4BIT CLKCTL_BUSMODE(1) /*!< 4-bit SDIO card bus mode */ +#define SDIO_BUSMODE_8BIT CLKCTL_BUSMODE(2) /*!< 8-bit SDIO card bus mode */ + +/* SDIO_CLK clock edge selection */ +#define SDIO_SDIOCLKEDGE_RISING ((uint32_t)0x00000000U)/*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */ +#define SDIO_SDIOCLKEDGE_FALLING SDIO_CLKCTL_CLKEDGE /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */ + +/* clock bypass enable or disable */ +#define SDIO_CLOCKBYPASS_DISABLE ((uint32_t)0x00000000U)/*!< no bypass */ +#define SDIO_CLOCKBYPASS_ENABLE SDIO_CLKCTL_CLKBYP /*!< clock bypass */ + +/* SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLOCKPWRSAVE_DISABLE ((uint32_t)0x00000000U)/*!< SDIO_CLK clock is always on */ +#define SDIO_CLOCKPWRSAVE_ENABLE SDIO_CLKCTL_CLKPWRSAV /*!< SDIO_CLK closed when bus is idle */ + +/* SDIO command response type */ +#define CMDCTL_CMDRESP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define SDIO_RESPONSETYPE_NO CMDCTL_CMDRESP(0) /*!< no response */ +#define SDIO_RESPONSETYPE_SHORT CMDCTL_CMDRESP(1) /*!< short response */ +#define SDIO_RESPONSETYPE_LONG CMDCTL_CMDRESP(3) /*!< long response */ + +/* command state machine wait type */ +#define SDIO_WAITTYPE_NO ((uint32_t)0x00000000U)/*!< not wait interrupt */ +#define SDIO_WAITTYPE_INTERRUPT SDIO_CMDCTL_INTWAIT /*!< wait interrupt */ +#define SDIO_WAITTYPE_DATAEND SDIO_CMDCTL_WAITDEND /*!< wait the end of data transfer */ + +#define SDIO_RESPONSE0 ((uint32_t)0x00000000U)/*!< card response[31:0]/card response[127:96] */ +#define SDIO_RESPONSE1 ((uint32_t)0x00000001U)/*!< card response[95:64] */ +#define SDIO_RESPONSE2 ((uint32_t)0x00000002U)/*!< card response[63:32] */ +#define SDIO_RESPONSE3 ((uint32_t)0x00000003U)/*!< card response[31:1], plus bit 0 */ + +/* SDIO data block size */ +#define DATACTL_BLKSZ(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define SDIO_DATABLOCKSIZE_1BYTE DATACTL_BLKSZ(0) /*!< block size = 1 byte */ +#define SDIO_DATABLOCKSIZE_2BYTES DATACTL_BLKSZ(1) /*!< block size = 2 bytes */ +#define SDIO_DATABLOCKSIZE_4BYTES DATACTL_BLKSZ(2) /*!< block size = 4 bytes */ +#define SDIO_DATABLOCKSIZE_8BYTES DATACTL_BLKSZ(3) /*!< block size = 8 bytes */ +#define SDIO_DATABLOCKSIZE_16BYTES DATACTL_BLKSZ(4) /*!< block size = 16 bytes */ +#define SDIO_DATABLOCKSIZE_32BYTES DATACTL_BLKSZ(5) /*!< block size = 32 bytes */ +#define SDIO_DATABLOCKSIZE_64BYTES DATACTL_BLKSZ(6) /*!< block size = 64 bytes */ +#define SDIO_DATABLOCKSIZE_128BYTES DATACTL_BLKSZ(7) /*!< block size = 128 bytes */ +#define SDIO_DATABLOCKSIZE_256BYTES DATACTL_BLKSZ(8) /*!< block size = 256 bytes */ +#define SDIO_DATABLOCKSIZE_512BYTES DATACTL_BLKSZ(9) /*!< block size = 512 bytes */ +#define SDIO_DATABLOCKSIZE_1024BYTES DATACTL_BLKSZ(10) /*!< block size = 1024 bytes */ +#define SDIO_DATABLOCKSIZE_2048BYTES DATACTL_BLKSZ(11) /*!< block size = 2048 bytes */ +#define SDIO_DATABLOCKSIZE_4096BYTES DATACTL_BLKSZ(12) /*!< block size = 4096 bytes */ +#define SDIO_DATABLOCKSIZE_8192BYTES DATACTL_BLKSZ(13) /*!< block size = 8192 bytes */ +#define SDIO_DATABLOCKSIZE_16384BYTES DATACTL_BLKSZ(14) /*!< block size = 16384 bytes */ + +/* SDIO data transfer mode */ +#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000U)/*!< block transfer */ +#define SDIO_TRANSMODE_STREAM SDIO_DATACTL_TRANSMOD /*!< stream transfer or SDIO multibyte transfer */ + +/* SDIO data transfer direction */ +#define SDIO_TRANSDIRECTION_TOCARD ((uint32_t)0x00000000U)/*!< write data to card */ +#define SDIO_TRANSDIRECTION_TOSDIO SDIO_DATACTL_DATADIR /*!< read data from card */ + +/* SDIO read wait type */ +#define SDIO_READWAITTYPE_DAT2 ((uint32_t)0x00000000U)/*!< read wait control using SDIO_DAT[2] */ +#define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ + +/* function declarations */ +/* deinitialize the SDIO */ +void sdio_deinit(void); +/* configure the SDIO clock */ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division); +/* enable hardware clock control */ +void sdio_hardware_clock_enable(void); +/* disable hardware clock control */ +void sdio_hardware_clock_disable(void); +/* set different SDIO card bus mode */ +void sdio_bus_mode_set(uint32_t bus_mode); +/* set the SDIO power state */ +void sdio_power_state_set(uint32_t power_state); +/* get the SDIO power state */ +uint32_t sdio_power_state_get(void); +/* enable SDIO_CLK clock output */ +void sdio_clock_enable(void); +/* disable SDIO_CLK clock output */ +void sdio_clock_disable(void); + +/* configure the command index, argument, response type, wait type and CSM to send command */ +/* configure the command and response */ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); +/* set the command state machine wait type */ +void sdio_wait_type_set(uint32_t wait_type); +/* enable the CSM(command state machine) */ +void sdio_csm_enable(void); +/* disable the CSM(command state machine) */ +void sdio_csm_disable(void); +/* get the last response command index */ +uint8_t sdio_command_index_get(void); +/* get the response for the last received command */ +uint32_t sdio_response_get(uint32_t responsex); + +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer */ +/* configure the data timeout, data length and data block size */ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); +/* configure the data transfer mode and direction */ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction); +/* enable the DSM(data state machine) for data transfer */ +void sdio_dsm_enable(void); +/* disable the DSM(data state machine) */ +void sdio_dsm_disable(void); +/* write data(one word) to the transmit FIFO */ +void sdio_data_write(uint32_t data); +/* read data(one word) from the receive FIFO */ +uint32_t sdio_data_read(void); +/* get the number of remaining data bytes to be transferred to card */ +uint32_t sdio_data_counter_get(void); +/* get the number of words remaining to be written or read from FIFO */ +uint32_t sdio_fifo_counter_get(void); +/* enable the DMA request for SDIO */ +void sdio_dma_enable(void); +/* disable the DMA request for SDIO */ +void sdio_dma_disable(void); + +/* get the flags state of SDIO */ +FlagStatus sdio_flag_get(uint32_t flag); +/* clear the pending flags of SDIO */ +void sdio_flag_clear(uint32_t flag); +/* enable the SDIO interrupt */ +void sdio_interrupt_enable(uint32_t int_flag); +/* disable the SDIO interrupt */ +void sdio_interrupt_disable(uint32_t int_flag); +/* get the interrupt flags state of SDIO */ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); +/* clear the interrupt pending flags of SDIO */ +void sdio_interrupt_flag_clear(uint32_t int_flag); + +/* enable the read wait mode(SD I/O only) */ +void sdio_readwait_enable(void); +/* disable the read wait mode(SD I/O only) */ +void sdio_readwait_disable(void); +/* enable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_enable(void); +/* disable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_disable(void); +/* set the read wait type(SD I/O only) */ +void sdio_readwait_type_set(uint32_t readwait_type); +/* enable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_enable(void); +/* disable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_disable(void); +/* enable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_enable(void); +/* disable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_disable(void); + +/* enable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_enable(void); +/* disable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_disable(void); +/* enable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_enable(void); +/* disable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_disable(void); +/* enable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_enable(void); +/* disable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_disable(void); + +#endif /* GD32F10X_SDIO_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h new file mode 100644 index 0000000000..f3553253f2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h @@ -0,0 +1,327 @@ +/*! + \file gd32f10x_spi.h + \brief definitions for the SPI + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_SPI_H +#define GD32F10X_SPI_H + +#include "gd32f10x.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3,5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR BITS(0,15) /*!< CRC polynomial value */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC value */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCR BITS(0,15) /*!< TX CRC value */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4,5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8,9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transtype */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by handware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescale factor */ +}spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by software */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1,2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI struct with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph,uint32_t mode, uint32_t standard, uint32_t ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* DMA communication */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* normal mode communication */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +#endif /* GD32F10X_SPI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h new file mode 100644 index 0000000000..0b4ca98237 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h @@ -0,0 +1,729 @@ +/*! + \file gd32f10x_timer.h + \brief definitions for the TIMER + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_TIMER_H +#define GD32F10X_TIMER_H + +#include "gd32f10x.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) +#define TIMER7 (TIMER_BASE + 0x00013400U) +#define TIMER8 (TIMER_BASE + 0x00014C00U) +#define TIMER9 (TIMER_BASE + 0x00015000U) +#define TIMER10 (TIMER_BASE + 0x00015400U) +#define TIMER11 (TIMER_BASE + 0x00001800U) +#define TIMER12 (TIMER_BASE + 0x00001C00U) +#define TIMER13 (TIMER_BASE + 0x00002000U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER channel complementary protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5,6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0,2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4,6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8,11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 over capture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 over capture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 over capture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 over capture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0,1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4,6) /*!< channel 0 output compare control */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8,9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12,14) /*!< channel 1 output compare control */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2,3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4,7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10,11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12,15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0,1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4,6) /*!< channel 2 output compare control */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8,9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12,14) /*!< channel 3 output compare control */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2,3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4,7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10,11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0,15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0,15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0,15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0,7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8,9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0,4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8,12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0,15) /*!< DMA transfer buffer address */ + +/* constants definitions */ +/* TIMER init parameter struct definitions */ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint32_t period; /*!< period value */ + uint16_t clockdivision; /*!< clock division value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +}timer_parameter_struct; + +/* break parameter struct definitions*/ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +}timer_break_parameter_struct; + +/* channel output parameter struct definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +}timer_oc_parameter_struct; + +/* channel input parameter struct definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +}timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INT_UP /*!< update interrupt */ +#define TIMER_INT_FLAG_CH0 TIMER_INT_CH0 /*!< channel 0 interrupt */ +#define TIMER_INT_FLAG_CH1 TIMER_INT_CH1 /*!< channel 1 interrupt */ +#define TIMER_INT_FLAG_CH2 TIMER_INT_CH2 /*!< channel 2 interrupt */ +#define TIMER_INT_FLAG_CH3 TIMER_INT_CH3 /*!< channel 3 interrupt */ +#define TIMER_INT_FLAG_CMT TIMER_INT_CMT /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INT_TRG /*!< trigger interrupt */ +#define TIMER_INT_FLAG_BRK TIMER_INT_BRK + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT TIMER_CTL1_DMAS /*!< DMA request of channel n is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel n is sent when channel n event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW TIMER_SWEVG_UPG /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000000U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE TIMER_CTL0_SPM /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000000U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR TIMER_CTL0_UPS /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000000U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4,7)) */ + +/* channel enable state */ +#define TIMER_CCX_ENABLE ((uint16_t)0x0001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint16_t)0x0000U) /*!< channel disable */ + +/* channel complementary output enable state */ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< frozen mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< set the channel output */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< clear the channel output */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle on match */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode*/ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers update by when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI TIMER_CTL1_CCUC /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ +#define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ + +/* timer input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4 */ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channel 0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE TIMER_SMCFG_MSM /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000000U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE TIMER_CTL1_TI0S /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0..4,7..13) write CHxVAL register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)TIMER_CFG_OUTSEL) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* function declarations */ +/* TIMER timebase */ +/* deinit a TIMER */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter struct */ +void timer_struct_para_init(timer_parameter_struct* initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +/* enable a TIMER */ +void timer_enable(uint32_t timer_periph); +/* disable a TIMER */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* timer DMA and event */ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter struct */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER interrupt and flag */ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flag */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flag */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +#endif /* GD32E10X_TIMER_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h new file mode 100644 index 0000000000..8a3ea37581 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h @@ -0,0 +1,377 @@ +/*! + \file gd32f10x_usart.h + \brief definitions for the USART + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.1, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_USART_H +#define GD32F10X_USART_H + +#include "gd32f10x.h" + +/* USARTx(x=0,1,2)/UARTx(x=3,4) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE+(0x00000400U)) /*!< USART2 base address */ +#define UART3 (USART_BASE+(0x00000800U)) /*!< UART3 base address */ +#define UART4 (USART_BASE+(0x00000C00U)) /*!< UART4 base address */ +#define USART0 (USART_BASE+(0x0000F400U)) /*!< USART0 base address */ + +/* registers definitions */ +#define USART_STAT(usartx) REG32((usartx) + (0x00000000U)) /*!< USART status register */ +#define USART_DATA(usartx) REG32((usartx) + (0x00000004U)) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + (0x00000008U)) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + (0x0000000CU)) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + (0x00000010U)) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + (0x00000014U)) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + (0x00000018U)) /*!< USART guard time and prescaler register */ + +/* bits definitions */ +/* USARTx_STAT */ +#define USART_STAT_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT_TC BIT(6) /*!< transmission complete */ +#define USART_STAT_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & (0x0000FFFFU)) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & (0x0000001FU)) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & (0x001F0000U)) >> 16) + +/* register offset */ +#define USART_STAT_REG_OFFSET (0x00000000U) /*!< STAT register offset */ +#define USART_CTL0_REG_OFFSET (0x0000000CU) /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET (0x00000010U) /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET (0x00000014U) /*!< CTL2 register offset */ + +/* USART flags */ +typedef enum +{ + /* flags in STAT register */ + USART_FLAG_CTSF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBDF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLEF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 0U), /*!< parity error flag */ +}usart_flag_enum; + +/* USART interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ +}usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ +}usart_interrupt_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); + +/* USART normal mode communication */ +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint16_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* LIN mode enable */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* LIN mode disable */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* half-duplex enable */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* half-duplex disable */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* clock enable */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* clock disable */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* guard time value configure in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut); +/* smartcard mode enable */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* smartcard mode disable */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* NACK enable in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* NACK disable in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* flag functions */ +/* get flag in STAT register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); + +/* interrupt functions */ +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); +/* clear interrupt flag in STAT register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag); +#endif /* GD32F10X_USART_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h new file mode 100644 index 0000000000..20a2c79c5f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h @@ -0,0 +1,89 @@ +/*! + \file gd32f10x_wwdgt.h + \brief definitions for the WWDGT + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_WWDGT_H +#define GD32F10X_WWDGT_H + +#include "gd32f10x.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE /*!< WWDGT base address */ + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x04U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x08U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0,6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0,6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7,8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32F10X_WWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c new file mode 100644 index 0000000000..d1d7addc7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c @@ -0,0 +1,932 @@ +/*! + \file gd32f10x_adc.c + \brief ADC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_adc.h" + +/* discontinuous mode macro*/ +#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U) + +/* ADC regular channel macro */ +#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U) +#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U) +#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U) +#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U) + +/* ADC sampling time macro */ +#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U) +#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U) +#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U) + +/* ADC inserted channel macro */ +#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U) +#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U) + +/* ADC inserted channel offset macro */ +#define ADC_OFFSET_LENGTH ((uint8_t)3U) +#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + /* reset ADC0 */ + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + /* reset ADC1 */ + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; +#ifndef GD32F10X_CL + case ADC2: + rcu_periph_reset_enable(RCU_ADC2RST); + rcu_periph_reset_disable(RCU_ADC2RST); + break; +#endif /* GD32F10X_CL */ + default: + break; + } +} + +/*! + \brief configure the ADC sync mode + \param[in] mode: ADC mode + only one parameter can be selected which is shown as below: + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] function: the function to config + only one parameter can be selected which is shown as below: + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (function & ADC_SCAN_MODE)){ + /* enable scan mode */ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* enable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* enable continuous mode */ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + /* disable scan mode */ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* disable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* disable continuous mode */ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] data_alignment: data alignment select + only one parameter can be selected which is shown as below: + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + /* MSB alignment */ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + /* LSB alignment */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + /* enable ADC */ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + /* disable ADC */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC1 calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + /* enable DMA request */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + /* disable DMA request */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel, the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + /* disable discontinuous mode of regular & inserted channel */ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC)); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* config the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + /* enable regular channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + /* enable inserted channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + /* disable discontinuous mode of regular & inserted channel */ + default: + break; + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the length of regular channel group */ + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + case ADC_INSERTED_CHANNEL: + /* configure the length of inserted channel group */ + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* ADC regular sequence config */ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + /* the regular group sequence rank is smaller than six */ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + /* the regular group sequence rank is smaller than twelve */ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + /* the regular group sequence rank is smaller than sixteen */ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + } + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the regular group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the regular group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + /* get inserted channel group length */ + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH))); + isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH)); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the inserted group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the inserted group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted channel3 + \param[in] offset: the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); + + if(num <= ADC_OFFSET_LENGTH){ + /* calculate the offset of the register */ + num = num * ADC_OFFSET_SHIFT_LENGTH; + /* config the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select + \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11: external interrupt line 11 + \arg ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select + \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select + \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure ADC regular group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + /* configure ADC inserted group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief configure ADC external trigger + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable ADC inserted channel group external trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* disable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* disable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable ADC regular channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable ADC inserted channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + /* read the data of channel 0 */ + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + /* read the data of channel 1 */ + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + /* read the data of channel 2 */ + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + /* read the data of channel 3 */ + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + /* analog watchdog channel select */ + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* regular channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + /* inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* regular and inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] low_threshold: analog watchdog low threshold, 0..4095 + \param[in] high_threshold: analog watchdog high threshold, 0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected which are shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the bit state of ADCx software start conversion + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWRCST)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the bit state of ADCx software inserted channel start conversion + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWICST)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the ADC interrupt bits + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc interrupt bits + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + return interrupt_flag; +} + +/*! + \brief clear the ADC flag + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* enable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + /* enable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + /* enable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* disable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + /* disable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + /* disable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c new file mode 100644 index 0000000000..fa8c59db56 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c @@ -0,0 +1,295 @@ +/*! + \file gd32f10x_bkp.c + \brief BKP driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_bkp.h" + +/* BKP register bits offset */ +#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number - 1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number - 1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_data_read(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number - 1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number - 1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + only one parameter can be selected which is shown as below: + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + /* configure BKP_OCTL_ROSEL with outputsel */ + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + /* configure BKP_OCTL_RCCV with value */ + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_RCCV; + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(void) +{ + BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN; +} + +/*! + \brief disable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(void) +{ + BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN; +} + +/*! + \brief set tamper pin active level + \param[in] level: tamper active level + only one parameter can be selected which is shown as below: + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(uint16_t level) +{ + uint16_t ctl = 0U; + + /* configure BKP_TPCTL_TPAL with level */ + ctl = BKP_TPCTL; + ctl &= (uint16_t)~BKP_TPCTL_TPAL; + ctl |= level; + BKP_TPCTL = ctl; +} + +/*! + \brief enable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_enable(void) +{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE; +} + +/*! + \brief disable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_disable(void) +{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE; +} + +/*! + \brief get tamper flag state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(void) +{ + if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear tamper flag state + \param[in] none + \param[out] none + \retval none +*/ +void bkp_flag_clear(void) +{ + BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); +} + +/*! + \brief get tamper interrupt flag state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(void) +{ + if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear tamper interrupt flag state + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(void) +{ + BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c new file mode 100644 index 0000000000..411b50f15c --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c @@ -0,0 +1,1053 @@ +/*! + \file gd32f10x_can.c + \brief CAN driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-11-27, V2.1.1, firmware for GD32F10x + \version 2020-07-14, V2.1.2, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_can.h" + +#define CAN_ERROR_HANDLE(s) do{}while(1) + +#define RFO1_CLEAR_VAL ((uint32_t)0x00000000U) /*!< RFO1 clear value */ +#define RFF1_CLEAR_VAL ((uint32_t)0x00000018U) /*!< RFF1 clear value */ + +/*! + \brief deinitialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_deinit(uint32_t can_periph) +{ +#ifdef GD32F10x_CL + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + }else{ + rcu_periph_reset_enable(RCU_CAN1RST); + rcu_periph_reset_disable(RCU_CAN1RST); + } +#else + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + } +#endif +} + +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + +/*! + \brief initialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init) +{ + uint32_t timeout = CAN_TIMEOUT; + ErrStatus flag = ERROR; + + /* disable sleep mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + /* enable initialize mode */ + CAN_CTL(can_periph) |= CAN_CTL_IWMOD; + /* wait ACK */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check initialize working success */ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + /* set the bit timing register */ + CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ + BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ + BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ + BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ + BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + + /* time trigger communication mode */ + if(ENABLE == can_parameter_init->time_triggered){ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + } + /* automatic bus-off managment */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + CAN_CTL(can_periph) |= CAN_CTL_ABOR; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; + } + /* automatic wakeup mode */ + if(ENABLE == can_parameter_init->auto_wake_up){ + CAN_CTL(can_periph) |= CAN_CTL_AWU; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_AWU; + } + /* automatic retransmission mode disable */ + if(ENABLE == can_parameter_init->no_auto_retrans){ + CAN_CTL(can_periph) |= CAN_CTL_ARD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite){ + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; + } + /* transmit fifo order */ + if(ENABLE == can_parameter_init->trans_fifo_order){ + CAN_CTL(can_periph) |= CAN_CTL_TFO; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TFO; + } + /* disable initialize mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; + timeout = CAN_TIMEOUT; + /* wait the ACK */ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check exit initialize mode */ + if(0U != timeout){ + flag = SUCCESS; + } + } + return flag; +} + +/*! + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +{ + uint32_t val = 0U; + + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* disable filter */ + CAN_FW(CAN0) &= ~(uint32_t)val; + + /* filter 16 bits */ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + /* set filter 16 bits */ + CAN_FSCFG(CAN0) &= ~(uint32_t)val; + /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + } + /* filter 32 bits */ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + /* set filter 32 bits */ + CAN_FSCFG(CAN0) |= (uint32_t)val; + /* 32 bits list or first 32 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* 32 bits mask or second 32 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + } + + /* filter mode */ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + /* mask mode */ + CAN_FMCFG(CAN0) &= ~(uint32_t)val; + }else{ + /* list mode */ + CAN_FMCFG(CAN0) |= (uint32_t)val; + } + + /* filter FIFO */ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + /* FIFO0 */ + CAN_FAFIFO(CAN0) &= ~(uint32_t)val; + }else{ + /* FIFO1 */ + CAN_FAFIFO(CAN0) |= (uint32_t)val; + } + + /* filter working */ + if(ENABLE == can_filter_parameter_init->filter_enable){ + + CAN_FW(CAN0) |= (uint32_t)val; + } + + /* filter lock enable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief set CAN1 fliter start bank number + \param[in] start_bank: CAN1 start bank number + only one parameter can be selected which is shown as below: + \arg (1..27) + \param[out] none + \retval none +*/ +void can1_filter_start_bank(uint8_t start_bank) +{ + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* set CAN1 filter start number */ + CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; + CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); + /* filter lock enaable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief enable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_enable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) |= CAN_CTL_DFZ; +#ifdef GD32F10x_CL + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + }else{ + dbg_periph_enable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief disable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_disable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; +#ifdef GD32F10x_CL + if(CAN0 == can_periph){ + dbg_periph_disable(DBG_CAN0_HOLD); + }else{ + dbg_periph_disable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief enable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_enable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* enable the tcc mode */ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + /* enable time stamp */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; + } +} + +/*! + \brief disable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_disable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* disable the TCC mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + /* reset TSEN bits */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; + } +} + +/*! + \brief transmit CAN message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF + \param[out] none + \retval mailbox_number +*/ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +{ + uint8_t mailbox_number = CAN_MAILBOX0; + + /* select one empty mailbox */ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + mailbox_number = CAN_MAILBOX0; + }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + mailbox_number = CAN_MAILBOX1; + }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + mailbox_number = CAN_MAILBOX2; + }else{ + mailbox_number = CAN_NOMAILBOX; + } + /* return no mailbox empty */ + if(CAN_NOMAILBOX == mailbox_number){ + return CAN_NOMAILBOX; + } + + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; + if(CAN_FF_STANDARD == transmit_message->tx_ff){ + /* set transmit mailbox standard identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ + transmit_message->tx_ft); + }else{ + /* set transmit mailbox extended identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ + transmit_message->tx_ff | \ + transmit_message->tx_ft); + } + /* set the data length */ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; + CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; + /* set the data */ + CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); + CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); + /* enable transmission */ + CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; + + return mailbox_number; +} + +/*! + \brief get CAN transmit state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOX(x=0,1,2) + \param[out] none + \retval can_transmit_state_enum +*/ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) +{ + can_transmit_state_enum state = CAN_TRANSMIT_FAILED; + uint32_t val = 0U; + + /* check selected mailbox state */ + switch(mailbox_number){ + /* mailbox0 */ + case CAN_MAILBOX0: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); + break; + /* mailbox1 */ + case CAN_MAILBOX1: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); + break; + /* mailbox2 */ + case CAN_MAILBOX2: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); + break; + default: + val = CAN_TRANSMIT_FAILED; + break; + } + + switch(val){ + /* transmit pending */ + case (CAN_STATE_PENDING): + state = CAN_TRANSMIT_PENDING; + break; + /* mailbox0 transmit succeeded */ + case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + state = CAN_TRANSMIT_OK; + break; + /* mailbox1 transmit succeeded */ + case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + state = CAN_TRANSMIT_OK; + break; + /* mailbox2 transmit succeeded */ + case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + state = CAN_TRANSMIT_OK; + break; + /* transmit failed */ + default: + state = CAN_TRANSMIT_FAILED; + break; + } + return state; +} + +/*! + \brief stop CAN transmission + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOXx(x=0,1,2) + \param[out] none + \retval none +*/ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) +{ + if(CAN_MAILBOX0 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } + }else if(CAN_MAILBOX1 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } + }else if(CAN_MAILBOX2 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } + }else{ + /* illegal parameters */ + } +} + +/*! + \brief CAN receive message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] fifo_number + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 + \retval none +*/ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +{ + /* get the frame format */ + receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); + if(CAN_FF_STANDARD == receive_message->rx_ff){ + /* get standard identifier */ + receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + }else{ + /* get extended identifier */ + receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + } + + /* get frame type */ + receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); + /* filtering index */ + receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + /* get recevie data length */ + receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + + /* receive data */ + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + + /* release FIFO */ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else{ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + } +} + +/*! + \brief release FIFO0 + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval none +*/ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) +{ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else if(CAN_FIFO1 == fifo_number){ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + }else{ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); + } +} + +/*! + \brief CAN receive message length + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval message length +*/ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) +{ + uint8_t val = 0U; + + if(CAN_FIFO0 == fifo_number){ + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); + }else{ + /* illegal parameters */ + } + return val; +} + +/*! + \brief set CAN working mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] can_working_mode + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) +{ + ErrStatus flag = ERROR; + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode){ + /* disable sleep mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); + /* set initialize mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; + /* wait the acknowledge */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_NORMAL == working_mode){ + /* enter normal mode */ + CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); + /* wait the acknowledge */ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + timeout--; + } + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_SLEEP == working_mode){ + /* disable initialize mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); + /* set sleep mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; + /* wait the acknowledge */ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else{ + flag = ERROR; + } + return flag; +} + +/*! + \brief wake up CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_wakeup(uint32_t can_periph) +{ + ErrStatus flag = ERROR; + uint32_t timeout = CAN_TIMEOUT; + + /* wakeup */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + timeout--; + } + /* check state */ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + return flag; +} + +/*! + \brief get CAN error type + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure +*/ +can_error_enum can_error_get(uint32_t can_periph) +{ + can_error_enum error; + error = CAN_ERROR_NONE; + + /* get error type */ + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); + return error; +} + +/*! + \brief get CAN receive error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval error number +*/ +uint8_t can_receive_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief get CAN transmit error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval error number +*/ +uint8_t can_transmit_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + +/*! + \brief get CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) +{ + /* get flag and interrupt enable state */ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \param[out] none + \retval none +*/ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag) +{ + if (flag == CAN_FLAG_RFO1){ + CAN_REG_VAL(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_FLAG_RFF1){ + CAN_REG_VAL(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); + } +} + +/*! + \brief get CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFL0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFL1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); + } + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \param[out] none + \retval none +*/ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + if (flag == CAN_INT_FLAG_RFO1){ + CAN_REG_VALS(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_INT_FLAG_RFF1){ + CAN_REG_VALS(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c new file mode 100644 index 0000000000..d2a3f12761 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c @@ -0,0 +1,130 @@ +/*! + \file gd32f10x_crc.c + \brief CRC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register to the value of initializaiton data register + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specify 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = array[index]; + } + return (CRC_DATA); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c new file mode 100644 index 0000000000..482c8a0cb6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c @@ -0,0 +1,558 @@ +/*! + \file gd32f10x_dac.c + \brief DAC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_dac.h" + +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + +/*! + \brief deinitialize DAC + \param[in] none + \param[out] none + \retval none +*/ +void dac_deinit(void) +{ + rcu_periph_reset_enable(RCU_DACRST); + rcu_periph_reset_disable(RCU_DACRST); +} + +/*! + \brief enable DAC + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DEN0; + }else{ + DAC_CTL |= DAC_CTL_DEN1; + } +} + +/*! + \brief disable DAC + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DEN1; + } +} + +/*! + \brief enable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DDMAEN0; + }else{ + DAC_CTL |= DAC_CTL_DDMAEN1; + } +} + +/*! + \brief disable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDMAEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DDMAEN1; + } +} + +/*! + \brief enable DAC output buffer + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DBOFF0; + }else{ + DAC_CTL &= ~DAC_CTL_DBOFF1; + } +} + +/*! + \brief disable DAC output buffer + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DBOFF0; + }else{ + DAC_CTL |= DAC_CTL_DBOFF1; + } +} + +/*! + \brief get DAC output value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + +/*! + \brief enable DAC trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DTEN0; + }else{ + DAC_CTL |= DAC_CTL_DTEN1; + } +} + +/*! + \brief disable DAC trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DTEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DTEN1; + } +} + +/*! + \brief set DAC trigger source + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: + \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO + \arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO (for GD32F10X_CL) + \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO + \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO + \arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO + \arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO + \arg DAC_TRIGGER_T7_TRGO: TIMER7 TRGO (for GD32F10X_MD and GD32F10X_HD and GD32F10X_XD) + \arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event + \arg DAC_TRIGGER_SOFTWARE: software trigger + \param[out] none + \retval none +*/ +void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL0; + DAC_CTL |= triggersource; + }else{ + /* configure DAC1 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL1; + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; + } +} + +/*! + \brief configure DAC wave mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] wave_mode + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_DISABLE: wave disable + \arg DAC_WAVE_MODE_LFSR: LFSR noise mode + \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode + \param[out] none + \retval none +*/ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM0; + DAC_CTL |= wave_mode; + }else{ + /* configure DAC1 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM1; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC wave bit width + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] bit_width + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 + \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 + \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 + \arg DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4 + \arg DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5 + \arg DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6 + \arg DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7 + \arg DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8 + \arg DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9 + \arg DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10 + \arg DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11 + \arg DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12 + \param[out] none + \retval none +*/ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= bit_width; + }else{ + /* configure DAC1 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC LFSR noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] unmask_bits + only one parameter can be selected which is shown as below: + \arg DAC_LFSR_BIT0: unmask the LFSR bit0 + \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] + \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] + \arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0] + \arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0] + \arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0] + \arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0] + \arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0] + \arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0] + \arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0] + \arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0] + \arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0] + \param[out] none + \retval none +*/ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= unmask_bits; + }else{ + /* configure DAC1 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC triangle noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] amplitude + only one parameter can be selected which is shown as below: + \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 + \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 + \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 + \arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15 + \arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31 + \arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63 + \arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127 + \arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255 + \arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511 + \arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023 + \arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047 + \arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095 + \param[out] none + \retval none +*/ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= amplitude; + }else{ + /* configure DAC1 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL |= (ctl); +} + +/*! + \brief disable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL &= (~ctl); +} + +/*! + \brief enable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_enable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT |= (swt); +} + +/*! + \brief disable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_disable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT &= (~swt); +} + +/*! + \brief enable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL &= (~ctl); +} + +/*! + \brief disable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL |= (ctl); +} + +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c new file mode 100644 index 0000000000..937e40c54d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c @@ -0,0 +1,152 @@ +/*! + \file gd32f10x_dbg.c + \brief DBG driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_dbg.h" + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_CTL |= (uint32_t)dbg_periph; +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD and CL series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_CTL &= ~(uint32_t)dbg_periph; +} + +/*! + \brief enable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_enable(void) +{ + DBG_CTL |= DBG_CTL_TRACE_IOEN; +} + +/*! + \brief disable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_disable(void) +{ + DBG_CTL &= ~DBG_CTL_TRACE_IOEN; +} + +/*! + \brief trace pin mode selection + \param[in] trace_mode: + only one parameter can be selected which is shown as below: + \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 + \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 + \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 + \param[out] none + \retval none +*/ +void dbg_trace_pin_mode_set(uint32_t trace_mode) +{ + DBG_CTL &= ~DBG_CTL_TRACE_MODE; + DBG_CTL |= trace_mode; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c new file mode 100644 index 0000000000..8908bd734f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c @@ -0,0 +1,737 @@ +/*! + \file gd32f10x_dma.c + \brief DMA driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-10-30, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_dma.h" + +#define DMA_WRONG_HANDLE while(1){} + + /* check whether peripheral matches channels or not */ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx); + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* disable DMA a channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width, */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] number: the number of remaining data to be transferred by the DMA + \arg 0x0000-0xFFFF + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + } else { + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + /* check whether the flag is set or not */ + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear the flag of a DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + + switch(flag){ + case DMA_INT_FLAG_FTF: + /* check whether the full transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + /* check whether the half transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + /* check whether the error interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + default: + DMA_WRONG_HANDLE + } + + /* when the interrupt flag is set and enabled, return SET */ + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief check whether peripheral and channels match + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA_CHx(x=0..6) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx) +{ + ErrStatus val = SUCCESS; + + if(DMA1 == dma_periph){ + /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */ + if(channelx > DMA_CH4){ + val = ERROR; + } + } + + return val; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c new file mode 100644 index 0000000000..13866c84f4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c @@ -0,0 +1,3079 @@ +/*! + \file gd32f10x_enet.c + \brief ENET driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_enet.h" + +#ifdef GD32F10X_CL + +#if defined (__CC_ARM) /*!< ARM compiler */ +__align(4) +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +__align(4) +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +__align(4) +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +__align(4) +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined ( __ICCARM__ ) /*!< IAR compiler */ +#pragma data_alignment=4 +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +#pragma data_alignment=4 +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +#pragma data_alignment=4 +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +#pragma data_alignment=4 +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ + +#endif /* __CC_ARM */ + +/* global transmit and receive descriptors pointers */ +enet_descriptors_struct *dma_current_txdesc; +enet_descriptors_struct *dma_current_rxdesc; + +/* structure pointer of ptp descriptor for normal mode */ +enet_descriptors_struct *dma_current_ptp_txdesc = NULL; +enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; + +/* init structure parameters for ENET initialization */ +static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static uint32_t enet_unknow_err = 0U; + +/* array of register offset for debug information get */ +static const uint16_t enet_reg_tab[] = { +0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x1080, 0x001C, 0x0028, 0x002C, +0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, + +0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1048, 0x104C, +0x1050, 0x1054}; + + +/*! + \brief deinitialize the ENET, and reset structure parameters for ENET initialization + \param[in] none + \param[out] none + \retval none +*/ +void enet_deinit(void) +{ + rcu_periph_reset_enable(RCU_ENETRST); + rcu_periph_reset_disable(RCU_ENETRST); + enet_initpara_reset(); +} + +/*! + \brief configure the parameters which are usually less cared for initialization + note -- this function must be called before enet_init(), otherwise + configuration will be no effect + \param[in] option: different function option, which is related to several parameters, + only one parameter can be selected which is shown as below, refer to enet_option_enum + \arg FORWARD_OPTION: choose to configure the frame forward related parameters + \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters + \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters + \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters + \arg STORE_OPTION: choose to configure the store forward mode related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg VLAN_OPTION: choose to configure vlan related parameters + \arg FLOWCTL_OPTION: choose to configure flow control related parameters + \arg HASHH_OPTION: choose to configure hash high + \arg HASHL_OPTION: choose to configure hash low + \arg FILTER_OPTION: choose to configure frame filter related parameters + \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters + \arg TIMER_OPTION: choose to configure time counter related parameters + \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below + FORWARD_OPTION related parameters: + - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; + - ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ; + - ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE . + DMABUS_OPTION related parameters: + - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; + - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; + DMA_MAXBURST_OPTION related parameters: + - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ + ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ + ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/ + ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/ + ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ; + - ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/ + ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/ + ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/ + ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/ + ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ; + - ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ; + DMA_ARBITRATION_OPTION related parameters: + - ENET_ARBITRATION_RXPRIORTX / ENET_ARBITRATION_RXTX_1_1 + / ENET_ARBITRATION_RXTX_2_1/ ENET_ARBITRATION_RXTX_3_1 + / ENET_ARBITRATION_RXTX_4_1. + STORE_OPTION related parameters: + - ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ; + - ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ; + - ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/ + ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ; + - ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/ + ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/ + ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/ + ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES . + DMA_OPTION related parameters: + - ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ; + - ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE . + VLAN_OPTION related parameters: + - ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ; + - MAC_VLT_VLTI(regval) . + FLOWCTL_OPTION related parameters: + - MAC_FCTL_PTM(regval) ; + - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; + - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; + - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; + - ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE . + HASHH_OPTION related parameters: + - 0x0~0xFFFF FFFFU + HASHL_OPTION related parameters: + - 0x0~0xFFFF FFFFU + FILTER_OPTION related parameters: + - ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/ + ENET_SRC_FILTER_DISABLE ; + - ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ; + - ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/ + ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ; + - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ + ENET_UNICAST_FILTER_PERFECT ; + - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + HALFDUPLEX_OPTION related parameters: + - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; + - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; + - ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ; + - ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/ + ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ; + - ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE . + TIMER_OPTION related parameters: + - ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ; + - ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ; + INTERFRAMEGAP_OPTION related parameters: + - ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/ + ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ + ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ + ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . + \param[out] none + \retval none +*/ +void enet_initpara_config(enet_option_enum option, uint32_t para) +{ + switch(option){ + case FORWARD_OPTION: + /* choose to configure forward_frame, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; + enet_initpara.forward_frame = para; + break; + case DMABUS_OPTION: + /* choose to configure dmabus_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION; + enet_initpara.dmabus_mode = para; + break; + case DMA_MAXBURST_OPTION: + /* choose to configure dma_maxburst, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION; + enet_initpara.dma_maxburst = para; + break; + case DMA_ARBITRATION_OPTION: + /* choose to configure dma_arbitration, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION; + enet_initpara.dma_arbitration = para; + break; + case STORE_OPTION: + /* choose to configure store_forward_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)STORE_OPTION; + enet_initpara.store_forward_mode = para; + break; + case DMA_OPTION: + /* choose to configure dma_function, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_OPTION; + enet_initpara.dma_function = para; + break; + case VLAN_OPTION: + /* choose to configure vlan_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)VLAN_OPTION; + enet_initpara.vlan_config = para; + break; + case FLOWCTL_OPTION: + /* choose to configure flow_control, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION; + enet_initpara.flow_control = para; + break; + case HASHH_OPTION: + /* choose to configure hashtable_high, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHH_OPTION; + enet_initpara.hashtable_high = para; + break; + case HASHL_OPTION: + /* choose to configure hashtable_low, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHL_OPTION; + enet_initpara.hashtable_low = para; + break; + case FILTER_OPTION: + /* choose to configure framesfilter_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FILTER_OPTION; + enet_initpara.framesfilter_mode = para; + break; + case HALFDUPLEX_OPTION: + /* choose to configure halfduplex_param, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION; + enet_initpara.halfduplex_param = para; + break; + case TIMER_OPTION: + /* choose to configure timer_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; + enet_initpara.timer_config = para; + break; + case INTERFRAMEGAP_OPTION: + /* choose to configure interframegap, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION; + enet_initpara.interframegap = para; + break; + default: + break; + } +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters and the less cared + parameters + \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation + \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex + \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex + \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex + \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex + \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII + \param[in] checksum: IP frame checksum offload function, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function + \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function + \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped + \param[in] recept: frame filter function, only one parameter can be selected + which is shown as below, refer to enet_frmrecept_enum + \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled + \arg ENET_RECEIVEALL: all received frame are forwarded to application + \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames + \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) +{ + uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t media_temp = 0U; + uint32_t timeout = 0U; + uint16_t phy_value = 0U; + ErrStatus phy_state= ERROR, enet_state = ERROR; + + /* PHY interface configuration, configure SMI clock and reset PHY chip */ + if(ERROR == enet_phy_config()){ + _ENET_DELAY_(PHY_RESETDELAY); + if(ERROR == enet_phy_config()){ + return enet_state; + } + } + /* initialize ENET peripheral with generally concerned parameters */ + enet_default_init(); + + /* 1st, configure mediamode */ + media_temp = (uint32_t)mediamode; + /* if is PHY auto negotiation */ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + /* wait for PHY_LINKED_STATUS bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_LINKED_STATUS; + timeout++; + }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* enable auto-negotiation */ + phy_value = PHY_AUTONEGOTIATION; + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_AUTONEGO_COMPLETE; + timeout++; + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* read the result of the auto-negotiation */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + /* configure the duplex mode of MAC following the auto-negotiation result */ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + media_temp = ENET_MODE_FULLDUPLEX; + }else{ + media_temp = ENET_MODE_HALFDUPLEX; + } + /* configure the communication speed of MAC following the auto-negotiation result */ + if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){ + media_temp |= ENET_SPEEDMODE_10M; + }else{ + media_temp |= ENET_SPEEDMODE_100M; + } + }else{ + phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); + phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + /* PHY configuration need some time */ + _ENET_DELAY_(PHY_CONFIGDELAY); + } + /* after configuring the PHY, use mediamode to configure registers */ + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value |= media_temp; + ENET_MAC_CFG = reg_value; + + + /* 2st, configure checksum */ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~ENET_DMA_CTL_DTCERFD; + reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); + ENET_DMA_CTL = reg_value; + } + + /* 3rd, configure recept */ + ENET_MAC_FRMF |= (uint32_t)recept; + + /* 4th, configure different function options */ + /* configure forward_frame related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + reg_temp = enet_initpara.forward_frame; + + reg_value = ENET_MAC_CFG; + temp = reg_temp; + /* configure ENET_MAC_CFG register */ + reg_value &= (~ENET_MAC_CFG_APCD); + temp &= ENET_MAC_CFG_APCD; + reg_value |= temp; + ENET_MAC_CFG = reg_value; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value |= (temp >> 2); + ENET_DMA_CTL = reg_value; + } + + /* configure dmabus_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + temp = enet_initpara.dmabus_mode; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ + |ENET_DMA_BCTL_FPBL); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_maxburst related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + temp = enet_initpara.dma_maxburst; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_arbitration related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + temp = enet_initpara.dma_arbitration; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure store_forward_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + temp = enet_initpara.store_forward_mode; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + } + + /* configure dma_function related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + reg_temp = enet_initpara.dma_function; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + reg_value |= reg_temp; + ENET_DMA_CTL = reg_value; + } + + /* configure vlan_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + reg_temp = enet_initpara.vlan_config; + + reg_value = ENET_MAC_VLT; + /* configure ENET_MAC_VLT register */ + reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); + reg_value |= reg_temp; + ENET_MAC_VLT = reg_value; + } + + /* configure flow_control related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + reg_temp = enet_initpara.flow_control; + + reg_value = ENET_MAC_FCTL; + temp = reg_temp; + /* configure ENET_MAC_FCTL register */ + reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value |= temp; + ENET_MAC_FCTL = reg_value; + + reg_value = ENET_MAC_FCTH; + temp = reg_temp; + /* configure ENET_MAC_FCTH register */ + reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); + reg_value |= (temp >> 8); + ENET_MAC_FCTH = reg_value; + } + + /* configure hashtable_high related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + ENET_MAC_HLH = enet_initpara.hashtable_high; + } + + /* configure hashtable_low related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + ENET_MAC_HLL = enet_initpara.hashtable_low; + } + + /* configure framesfilter_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + reg_temp = enet_initpara.framesfilter_mode; + + reg_value = ENET_MAC_FRMF; + /* configure ENET_MAC_FRMF register */ + reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + reg_value |= reg_temp; + ENET_MAC_FRMF = reg_value; + } + + /* configure halfduplex_param related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + reg_temp = enet_initpara.halfduplex_param; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure timer_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + reg_temp = enet_initpara.timer_config; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure interframegap related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + reg_temp = enet_initpara.interframegap; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~ENET_MAC_CFG_IGBS; + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + enet_state = SUCCESS; + return enet_state; +} + +/*! + \brief reset all core internal registers located in CLK_TX and CLK_RX + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_software_reset(void) +{ + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + uint32_t dma_flag; + + /* reset all core internal registers located in CLK_TX and CLK_RX */ + ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; + + /* wait for reset operation complete */ + do{ + dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); + timeout++; + }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief check receive frame valid and return frame size + \param[in] none + \param[out] none + \retval size of received frame: 0x0 - 0x3FFF +*/ +uint32_t enet_rxframe_size_get(void) +{ + uint32_t size = 0U; + uint32_t status; + + /* get rdes0 information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + + /* if the desciptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + return 0U; + } + + /* if has any error, or the frame uses two or more descriptors */ + if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + /* get the size of the received data including CRC */ + size = GET_RDES0_FRML(status); + /* substract the CRC size */ + size = size - 4U; + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; + } + + /* return packet size */ + return size; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode */ + desc_status = ENET_TDES0_TCHM; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief handle current received frame data to application buffer + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the received frame data + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status); + size = size - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offsetbuffer1_addr) + offset)); + } + + }else{ + /* return ERROR */ + return ERROR; + } + } + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief handle application buffer data to transmit it + \param[in] buffer: pointer to the frame data to be transmitted, + note -- if the input is NULL, user should handle the data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) +{ + uint32_t offset = 0U; + uint32_t dma_tbu_flag, dma_tu_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief configure the transmit IP frame checksum offload calculation and insertion + \param[in] desc: the descriptor pointer which users want to configure + \param[in] checksum: IP frame checksum configuration + only one parameter can be selected which is shown as below + \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled + \arg ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled + \arg ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header + \arg ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated + \param[out] none + \retval none +*/ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum) +{ + desc->status &= ~ENET_TDES0_CM; + desc->status |= checksum; +} + +/*! + \brief ENET Tx and Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_enable(void) +{ + enet_tx_enable(); + enet_rx_enable(); +} + +/*! + \brief ENET Tx and Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_disable(void) +{ + enet_tx_disable(); + enet_rx_disable(); +} + +/*! + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: set MAC address 0 filter + \arg ENET_MAC_ADDRESS1: set MAC address 1 filter + \arg ENET_MAC_ADDRESS2: set MAC address 2 filter + \arg ENET_MAC_ADDRESS3: set MAC address 3 filter + \param[in] paddr: the buffer pointer which stores the MAC address + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[out] none + \retval none +*/ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); + REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr); +} + +/*! + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: get MAC address 0 filter + \arg ENET_MAC_ADDRESS1: get MAC address 1 filter + \arg ENET_MAC_ADDRESS2: get MAC address 2 filter + \arg ENET_MAC_ADDRESS3: get MAC address 3 filter + \param[out] paddr: the buffer pointer which is stored the MAC address + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \retval none +*/ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); + paddr[1] = ENET_GET_MACADDR(mac_addr, 1U); + paddr[2] = ENET_GET_MACADDR(mac_addr, 2U); + paddr[3] = ENET_GET_MACADDR(mac_addr, 3U); + paddr[4] = ENET_GET_MACADDR(mac_addr, 4U); + paddr[5] = ENET_GET_MACADDR(mac_addr, 5U); +} + +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + +/*! + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; +} + +/*! + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; +} + +/*! + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; +} + +/*! + \brief ENET Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE; + ENET_MAC_CFG &= ~ENET_MAC_CFG_REN; +} + +/*! + \brief put registers value into the application buffer + \param[in] type: register type which will be get, refer to enet_registers_type_enum, + only one parameter can be selected which is shown as below + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT + \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL + \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR + \param[in] num: the number of registers that the user want to get + \param[out] preg: the application buffer pointer for storing the register value + \retval none +*/ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) +{ + uint32_t offset = 0U, max = 0U, limit = 0U; + + offset = (uint32_t)type; + max = (uint32_t)type + num; + limit = sizeof(enet_reg_tab)/sizeof(uint16_t); + + /* prevent element in this array is out of range */ + if(max > limit){ + max = limit; + } + + for(; offset < max; offset++){ + /* get value of the corresponding register */ + *preg = REG32((ENET) + enet_reg_tab[offset]); + preg++; + } +} + +/*! + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable + \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_enable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: disable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_disable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter + \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter + \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter + \param[in] addr_mask: select which MAC address bytes will be mask, + one or more parameters can be selected which are shown as below + \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits + \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits + \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits + \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits + \param[in] filter_type: select which MAC address filter type will be selected, + only one parameter can be selected which is shown as below + \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame + \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame + \param[out] none + \retval none +*/ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) +{ + uint32_t reg; + + /* get the address filter register value which is to be configured */ + reg = REG32(ENET_ADDRH_BASE + mac_addr); + + /* clear and configure the address filter register */ + reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF); + reg |= (addr_mask | filter_type); + REG32(ENET_ADDRH_BASE + mac_addr) = reg; +} + +/*! + \brief PHY interface configuration (configure SMI clock and reset PHY chip) + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_config(void) +{ + uint32_t ahbclk; + uint32_t reg; + uint16_t phy_value; + ErrStatus enet_state = ERROR; + + /* clear the previous MDC clock */ + reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + /* get the HCLK frequency */ + ahbclk = rcu_clock_freq_get(CK_AHB); + + /* configure MDC clock according to HCLK frequency range */ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + reg |= ENET_MDC_HCLK_DIV16; + }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + reg |= ENET_MDC_HCLK_DIV26; + }else if(ENET_RANGE(ahbclk, 60000000U, 90000000U)){ + reg |= ENET_MDC_HCLK_DIV42; + }else if((ENET_RANGE(ahbclk, 90000000U, 108000000U))||(108000000U == ahbclk)){ + reg |= ENET_MDC_HCLK_DIV62; + }else{ + return enet_state; + } + ENET_MAC_PHY_CTL = reg; + + /* reset PHY */ + phy_value = PHY_RESET; + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + /* PHY reset need some time */ + _ENET_DELAY_(ENET_DELAY_TO); + + /* check whether PHY reset is complete */ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + + /* PHY reset complete */ + if(RESET == (phy_value & PHY_RESET)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief write to / read from a PHY register + \param[in] direction: only one parameter can be selected which is shown as below + \arg ENET_PHY_WRITE: write data to phy register + \arg ENET_PHY_READ: read data from phy register + \param[in] phy_address: 0x0 - 0x1F + \param[in] phy_reg: 0x0 - 0x1F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue) +{ + uint32_t reg, phy_flag; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* configure ENET_MAC_PHY_CTL with write/read operation */ + reg = ENET_MAC_PHY_CTL; + reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + + /* if do the write operation, write value to the register */ + if(ENET_PHY_WRITE == direction){ + ENET_MAC_PHY_DATA = *pvalue; + } + + /* do PHY write/read operation, and wait the operation complete */ + ENET_MAC_PHY_CTL = reg; + do{ + phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); + timeout++; + } + while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + enet_state = SUCCESS; + } + + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction){ + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + } + + return enet_state; +} + +/*! + \brief enable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_enable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* enable the PHY loopback mode */ + temp_phy |= PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief disable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_disable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* disable the PHY loopback mode */ + temp_phy &= (uint16_t)~PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief enable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_enable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG |= mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL |= (mask >> 2); +} + +/*! + \brief disable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_disable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG &= ~mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL &= ~(mask >> 2); +} + +/*! + \brief enable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_enable(uint32_t feature) +{ + ENET_MAC_FRMF |= feature; +} + +/*! + \brief disable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_disable(uint32_t feature) +{ + ENET_MAC_FRMF &= ~feature; +} + +/*! + \brief generate the pause frame, ENET will send pause frame after enable transmit flow control + this function only use in full-dulex mode + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state =ERROR; + uint32_t temp = 0U; + + /* in full-duplex mode, must make sure this bit is 0 before writing register */ + temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; + if(RESET == temp){ + ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; + enet_state = SUCCESS; + } + return enet_state; +} + +/*! + \brief configure the pause frame detect type + \param[in] detect: pause frame detect type, + only one parameter can be selected which is shown as below + \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also + use the MAC0 address to detecting pause frame + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + in IEEE802.3 can be detected + \param[out] none + \retval none +*/ +void enet_pauseframe_detect_config(uint32_t detect) +{ + ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT; + ENET_MAC_FCTL |= detect; +} + +/*! + \brief configure the pause frame parameters + \param[in] pausetime: pause time in transmit pause control frame + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, + this value must make sure to be less than configured pause time, only one parameter can be + selected which is shown as below + \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times + \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times + \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times + \arg ENET_PAUSETIME_MINUS256: pause time minus 256 slot times + \param[out] none + \retval none +*/ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) +{ + ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS); + ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold); +} + +/*! + \brief configure the threshold of the flow control(deactive and active threshold) + \param[in] deactive: the threshold of the deactive flow control, this value + should always be less than active flow control value, only one + parameter can be selected which is shown as below + \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[in] active: the threshold of the active flow control, only one parameter + can be selected which is shown as below + \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[out] none + \retval none +*/ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) +{ + ENET_MAC_FCTH = ((deactive | active) >> 8); +} + +/*! + \brief enable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_enable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL |= feature; +} + +/*! + \brief disable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_disable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL &= ~feature; +} + +/*! + \brief get the dma transmit/receive process state + \param[in] direction: choose the direction of dma process which users want to check, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: dma transmit process + \arg ENET_DMA_RX: dma receive process + \param[out] none + \retval state of dma process, the value range shows below: + ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING, + ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING, + ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING, + ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING +*/ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) +{ + uint32_t reval; + reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction); + return reval; +} + +/*! + \brief poll the DMA transmission/reception enable by writing any value to the + ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception + \param[in] direction: choose the direction of DMA process which users want to resume, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA transmit process + \arg ENET_DMA_RX: DMA receive process + \param[out] none + \retval none +*/ +void enet_dmaprocess_resume(enet_dmadirection_enum direction) +{ + if(ENET_DMA_TX == direction){ + ENET_DMA_TPEN = 0U; + }else{ + ENET_DMA_RPEN = 0U; + } +} + +/*! + \brief check and recover the Rx process + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxprocess_check_recovery(void) +{ + uint32_t status; + + /* get DAV information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + status &= ENET_RDES0_DAV; + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with + receive descriptor address pointer updated by RxDMA controller */ + if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && + (ENET_RDES0_DAV == status)){ + dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + } +} + +/*! + \brief flush the ENET transmit FIFO, and wait until the flush operation completes + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_txfifo_flush(void) +{ + uint32_t flush_state; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* set the FTF bit for flushing transmit FIFO */ + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + /* wait until the flush operation completes */ + do{ + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + timeout++; + }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(RESET == flush_state){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + only one parameter can be selected which is shown as below + \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table + \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by + the RxDMA controller + \arg ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller + \arg ENET_TX_DESC_TABLE: the start address of the transmit descriptor table + \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by + the TxDMA controller + \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller + \param[out] none + \retval address value +*/ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) +{ + uint32_t reval = 0U; + + reval = REG32((ENET) +(uint32_t)addr_get); + return reval; +} + +/*! + \brief get the Tx or Rx descriptor information + \param[in] desc: the descriptor pointer which users want to get information + \param[in] info_get: the descriptor information type which is selected, + only one parameter can be selected which is shown as below + \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size + \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size + \arg RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer + \arg TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted + \arg RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame + \arg TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame + \param[out] none + \retval descriptor information, if value is 0xFFFFFFFFU, means the false input parameter +*/ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch(info_get){ + case RXDESC_BUFFER_1_SIZE: + reval = GET_RDES1_RB1S(desc->control_buffer_size); + break; + case RXDESC_BUFFER_2_SIZE: + reval = GET_RDES1_RB2S(desc->control_buffer_size); + break; + case RXDESC_FRAME_LENGTH: + reval = GET_RDES0_FRML(desc->status); + if(reval > 4U){ + reval = reval - 4U; + }else{ + reval = 0U; + } + break; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_COLLISION_COUNT: + reval = GET_TDES0_COCNT(desc->status); + break; + default: + break; + } + return reval; +} + +/*! + \brief get the number of missed frames during receiving + \param[in] none + \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO + \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller + \retval none +*/ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) +{ + uint32_t temp_counter = 0U; + + temp_counter = ENET_DMA_MFBOCNT; + *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); + *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); +} + +/*! + \brief get the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_UFE: underflow error + \arg ENET_TDES0_EXD: excessive deferral + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_ECO: excessive collision + \arg ENET_TDES0_LCO: late collision + \arg ENET_TDES0_NCA: no carrier + \arg ENET_TDES0_LCA: loss of carrier + \arg ENET_TDES0_IPPE: IP payload error + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_JT: jabber timeout + \arg ENET_TDES0_ES: error summary + \arg ENET_TDES0_IPHE: IP header error + \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + + \arg ENET_RDES0_PCERR: payload checksum error + \arg ENET_RDES0_CERR: CRC error + \arg ENET_RDES0_DBERR: dribble bit error + \arg ENET_RDES0_RERR: receive error + \arg ENET_RDES0_RWDT: receive watchdog timeout + \arg ENET_RDES0_FRMT: frame type + \arg ENET_RDES0_LCO: late collision + \arg ENET_RDES0_IPHERR: IP frame header error + \arg ENET_RDES0_LDES: last descriptor + \arg ENET_RDES0_FDES: first descriptor + \arg ENET_RDES0_VTAG: VLAN tag + \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_LERR: length error + \arg ENET_RDES0_SAFF: SA filter fail + \arg ENET_RDES0_DERR: descriptor error + \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_DAFF: destination address filter fail + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + FlagStatus enet_flag = RESET; + + if ((uint32_t)RESET != (desc->status & desc_flag)){ + enet_flag = SET; + } + + return enet_flag; +} + +/*! + \brief set the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to set flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status |= desc_flag; +} + +/*! + \brief clear the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to clear flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status &= ~desc_flag; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size &= ~ENET_RDES1_DINTC; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will not set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size |= ENET_RDES1_DINTC; +} + +/*! + \brief drop current receive frame + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxframe_drop(void) +{ + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } + + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + } + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc++; + } + } + } +} + +/*! + \brief enable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_enable(uint32_t feature) +{ + ENET_DMA_CTL |= feature; +} + +/*! + \brief disable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_disable(uint32_t feature) +{ + ENET_DMA_CTL &= ~feature; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive ring mode and set buffer1 size */ + desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] timestamp: pointer to the table which stores the timestamp high and low + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); + } + + }else{ + return ERROR; + } + } + /* copy timestamp value from Rx descriptor to application array */ + timestamp[0] = dma_current_rxdesc->buffer1_addr; + timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with RxDMA descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_rxdesc ++; + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0U, timeout = 0U; + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->buffer1_addr; + timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_txdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with TxDMA descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; + } + } + return SUCCESS; +} + +/*! + \brief wakeup frame filter register pointer reset + \param[in] none + \param[out] none + \retval none +*/ +void enet_wum_filter_register_pointer_reset(void) +{ + ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR; +} + +/*! + \brief set the remote wakeup frame registers + \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) + \param[out] none + \retval none +*/ +void enet_wum_filter_config(uint32_t pdata[]) +{ + uint32_t num = 0U; + + /* configure ENET_MAC_RWFF register */ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + ENET_MAC_RWFF = pdata[num]; + } +} + +/*! + \brief enable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_POWER_DOWN: power down mode + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_enable(uint32_t feature) +{ + ENET_MAC_WUM |= feature; +} + +/*! + \brief disable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_disable(uint32_t feature) +{ + ENET_MAC_WUM &= (~feature); +} + +/*! + \brief reset the MAC statistics counters + \param[in] none + \param[out] none + \retval none +*/ +void enet_msc_counters_reset(void) +{ + /* reset all counters */ + ENET_MSC_CTL |= ENET_MSC_CTL_CTR; +} + +/*! + \brief enable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_enable(uint32_t feature) +{ + ENET_MSC_CTL |= feature; +} + +/*! + \brief disable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_disable(uint32_t feature) +{ + ENET_MSC_CTL &= (~feature); +} + +/*! + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter + \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter + \arg ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter + \arg ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter + \arg ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter + \arg ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter + \param[out] none + \retval the MSC counter value +*/ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) +{ + uint32_t reval; + + reval = REG32((ENET + (uint32_t)counter)); + + return reval; +} + +/*! + \brief change subsecond to nanosecond + \param[in] subsecond: subsecond value + \param[out] none + \retval the nanosecond value +*/ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) +{ + uint64_t val = subsecond * 1000000000Ull; + val >>= 31; + return (uint32_t)val; +} + +/*! + \brief change nanosecond to subsecond + \param[in] nanosecond: nanosecond value + \param[out] none + \retval the subsecond value +*/ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond) +{ + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return (uint32_t)val; +} + +/*! + \brief enable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_enable(uint32_t feature) +{ + ENET_PTP_TSCTL |= feature; +} + +/*! + \brief disable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_disable(uint32_t feature) +{ + ENET_PTP_TSCTL &= ~feature; +} + +/*! + \brief configure the PTP timestamp function + \param[in] func: only one parameter can be selected which is shown as below + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \arg ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating + \arg ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ + +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) +{ + uint32_t temp_config = 0U, temp_state = 0U; + uint32_t timeout = 0U; + ErrStatus enet_state = SUCCESS; + + switch(func){ + case ENET_PTP_ADDEND_UPDATE: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; + } + break; + case ENET_PTP_SYSTIME_UPDATE: + /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ + do{ + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; + } + break; + case ENET_PTP_SYSTIME_INIT: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; + } + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; + } + + return enet_state; +} + +/*! + \brief configure system time subsecond increment value + \param[in] subsecond: the value will be added to the subsecond value of system time, + this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_ptp_subsecond_increment_config(uint32_t subsecond) +{ + ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond); +} + +/*! + \brief adjusting the clock frequency only in fine update mode + \param[in] add: the value will be added to the accumulator register to achieve time synchronization + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_addend_config(uint32_t add) +{ + ENET_PTP_TSADDEND = add; +} + +/*! + \brief initialize or add/subtract to second of the system time + \param[in] sign: timestamp update positive or negative sign, + only one parameter can be selected which is shown as below + \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time + \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time + \param[in] second: initializing or adding/subtracting to second of the system time + \param[in] subsecond: the current subsecond of the system time + with 0.46 ns accuracy if required accuracy is 20 ns + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) +{ + ENET_PTP_TSUH = second; + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); +} + +/*! + \brief configure the expected target time + \param[in] second: the expected target second time + \param[in] nanosecond: the expected target nanosecond time (signed) + \param[out] none + \retval none +*/ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) +{ + ENET_PTP_ETH = second; + ENET_PTP_ETL = nanosecond; +} + +/*! + \brief get the current system time + \param[in] none + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \retval none +*/ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) +{ + uint32_t temp_sec = 0U, temp_subs = 0U; + + /* get the value of sysytem time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; + temp_subs = (uint32_t)ENET_PTP_TSL; + + /* get sysytem time and construct the enet_ptp_systime_struct structure */ + systime_struct->second = temp_sec; + systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); + systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); + systime_struct->sign = GET_PTP_TSL_STS(temp_subs); +} + +/*! + \brief configure and start PTP timestamp counter + \param[in] updatemethod: method for updating + \arg ENET_PTP_FINEMODE: fine correction method + \arg ENET_PTP_COARSEMODE: coarse correction method + \param[in] init_sec: second value for initializing system time + \param[in] init_subsec: subsecond value for initializing system time + \param[in] carry_cfg: the value to be added to the accumulator register (in fine method is used) + \param[in] accuracy_cfg: the value to be added to the subsecond value of system time + \param[out] none + \retval none +*/ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg) +{ + /* mask the timestamp trigger interrupt */ + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + + /* enable timestamp */ + enet_ptp_feature_enable(ENET_RXTX_TIMESTAMP); + + /* configure system time subsecond increment based on the PTP clock frequency */ + enet_ptp_subsecond_increment_config(accuracy_cfg); + + if(ENET_PTP_FINEMODE == updatemethod){ + /* fine correction method: configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + /* wait until update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + } + } + + /* choose the fine correction method */ + enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); +} + +/*! + \brief adjust frequency in fine method by configure addend register + \param[in] carry_cfg: the value to be added to the accumulator register + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) +{ + /* re-configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config((uint32_t)carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief update system time in coarse method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct) +{ + uint32_t subsecond_val; + uint32_t carry_cfg; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* save the carry_cfg value */ + carry_cfg = ENET_PTP_TSADDEND_TMSA; + + /* update the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + + /* wait until the update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + } + + /* write back the carry_cfg value, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief set system time in fine method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +{ + uint32_t subsecond_val; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + + /* wait until the system time initialzation finished */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + } +} + +/*! + \brief get the ptp flag status + \param[in] flag: ptp flag status to be checked + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_ptp_flag_get(uint32_t flag) +{ + FlagStatus bitstatus = RESET; + + if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + bitstatus = SET; + } + + return bitstatus; +} + +/*! + \brief reset the ENET initpara struct, call it before using enet_initpara_config() + \param[in] none + \param[out] none + \retval none +*/ +void enet_initpara_reset(void) +{ + enet_initpara.option_enable = 0U; + enet_initpara.forward_frame = 0U; + enet_initpara.dmabus_mode = 0U; + enet_initpara.dma_maxburst = 0U; + enet_initpara.dma_arbitration = 0U; + enet_initpara.store_forward_mode = 0U; + enet_initpara.dma_function = 0U; + enet_initpara.vlan_config = 0U; + enet_initpara.flow_control = 0U; + enet_initpara.hashtable_high = 0U; + enet_initpara.hashtable_low = 0U; + enet_initpara.framesfilter_mode = 0U; + enet_initpara.halfduplex_param = 0U; + enet_initpara.timer_config = 0U; + enet_initpara.interframegap = 0U; +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \param[in] none + \param[out] none + \retval none +*/ +static void enet_default_init(void) +{ + uint32_t reg_value = 0U; + + /* MAC */ + /* configure ENET_MAC_CFG register */ + reg_value = ENET_MAC_CFG; + reg_value &= MAC_CFG_MASK; + reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ + | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; + ENET_MAC_CFG = reg_value; + + /* configure ENET_MAC_FRMF register */ + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ + |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ + |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ + |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + + /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ + ENET_MAC_HLH = 0x0U; + + ENET_MAC_HLL = 0x0U; + + /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ + reg_value = ENET_MAC_FCTL; + reg_value &= MAC_FCTL_MASK; + reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ + |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ + |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + + ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES; + + /* configure ENET_MAC_VLT register */ + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); + + /* DMA */ + /* configure ENET_DMA_CTL register */ + reg_value = ENET_DMA_CTL; + reg_value &= DMA_CTL_MASK; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ + |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ + |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ + |ENET_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \ + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; + + /* configure ENET_DMA_BCTL register */ + reg_value = ENET_DMA_BCTL; + reg_value &= DMA_BCTL_MASK; + reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ + |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ + |ENET_FIXED_BURST_ENABLE; + ENET_DMA_BCTL = reg_value; +} + +#ifndef USE_DELAY +/*! + \brief insert a delay time + \param[in] ncount: specifies the delay time length + \param[out] none + \param[out] none +*/ +static void enet_delay(uint32_t ncount) +{ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--){ + } +} +#endif /* USE_DELAY */ + +#endif /* GD32F10X_CL */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c new file mode 100644 index 0000000000..3a9416d8a8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c @@ -0,0 +1,645 @@ +/*! + \file gd32f10x_exmc.c + \brief EXMC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_exmc.h" + +/* EXMC bank0 register reset value */ +#define BANK0_SNCTL0_REGION_RESET ((uint32_t)0x000030DBU) +#define BANK0_SNCTL1_2_3_REGION_RESET ((uint32_t)0x000030D2U) +#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) + +/* EXMC bank1/2 register reset mask*/ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000040U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC bank3 register reset mask*/ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000040U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC register bit offset */ +#define SNCTL_NRMUX_OFFSET ((uint32_t)1U) +#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U) +#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U) +#define SNCTL_WREN_OFFSET ((uint32_t)12U) +#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U) +#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U) +#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U) + +#define SNTCFG_AHLD_OFFSET ((uint32_t)4U) +#define SNTCFG_DSET_OFFSET ((uint32_t)8U) +#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U) + +#define SNWTCFG_WAHLD_OFFSET ((uint32_t)4U) +#define SNWTCFG_WDSET_OFFSET ((uint32_t)8U) +#define SNWTCFG_WBUSLAT_OFFSET ((uint32_t)16U) + +#define NPCTL_NDWTEN_OFFSET ((uint32_t)1U) +#define NPCTL_ECCEN_OFFSET ((uint32_t)6U) + +#define NPCTCFG_COMWAIT_OFFSET ((uint32_t)8U) +#define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) +#define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) + +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) + +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) + +#define INTEN_INTS_OFFSET ((uint32_t)3U) + +/*! + \brief deinitialize EXMC NOR/SRAM region + \param[in] norsram_region: select the region of bank0 + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_deinit(uint32_t norsram_region) +{ + /* reset the registers */ + if(EXMC_BANK0_NORSRAM_REGION0 == norsram_region){ + EXMC_SNCTL(norsram_region) = BANK0_SNCTL0_REGION_RESET; + }else{ + EXMC_SNCTL(norsram_region) = BANK0_SNCTL1_2_3_REGION_RESET; + } + + EXMC_SNTCFG(norsram_region) = BANK0_SNTCFG_RESET; + EXMC_SNWTCFG(norsram_region) = BANK0_SNWTCFG_RESET; +} + +/*! + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 + write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + write_timing: struct exmc_norsram_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | + EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | + EXMC_SNCTL_NRMUX )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )| + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )| + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; + } + + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)(((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET) | + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD)| + (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNWTCFG_WDSET) | + exmc_norsram_init_struct->write_timing->asyn_access_mode); + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } + + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; +} + +/*! + \brief initialize the struct exmc_norsram_parameter_struct + \param[in] none + \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + /* configure the structure with default value */ + exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; + exmc_norsram_init_struct->address_data_mux = ENABLE; + exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; + exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B; + exmc_norsram_init_struct->burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW; + exmc_norsram_init_struct->wrap_burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE; + exmc_norsram_init_struct->memory_write = ENABLE; + exmc_norsram_init_struct->nwait_signal = ENABLE; + exmc_norsram_init_struct->extended_mode = DISABLE; + exmc_norsram_init_struct->asyn_wait = DISABLE; + exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; + + /* read/write timing configure */ + exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK; + exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; + exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; + + /* write timing configure, when extended mode is used */ + exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; +} + +/*! + \brief enable EXMC NOR/PSRAM bank region + \param[in] norsram_region: specifie the region of NOR/PSRAM bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_enable(uint32_t norsram_region) +{ + EXMC_SNCTL(norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief disable EXMC NOR/PSRAM bank region + \param[in] norsram_region: specifie the region of NOR/PSRAM Bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_disable(uint32_t norsram_region) +{ + EXMC_SNCTL(norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief deinitialize EXMC NAND bank + \param[in] nand_bank: select the bank of NAND + \arg EXMC_BANKx_NAND(x=1..2) + \param[out] none + \retval none +*/ +void exmc_nand_deinit(uint32_t nand_bank) +{ + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + EXMC_NPCTL(nand_bank) = BANK1_2_NPCTL_RESET; + EXMC_NPINTEN(nand_bank) = BANK1_2_NPINTEN_RESET; + EXMC_NPCTCFG(nand_bank) = BANK1_2_NPCTCFG_RESET; + EXMC_NPATCFG(nand_bank) = BANK1_2_NPATCFG_RESET; +} + +/*! + \brief initialize EXMC NAND bank + \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter + nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND + ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + ecc_logic: ENABLE or DISABLE + databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; + EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; + EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; +} + +/*! + \brief initialize the struct exmc_nand_init_struct + \param[in] none + \param[out] the initialized struct exmc_nand_init_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default value */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief enable NAND bank + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_enable(uint32_t nand_bank) +{ + EXMC_NPCTL(nand_bank) |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable NAND bank + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_disable(uint32_t nand_bank) +{ + EXMC_NPCTL(nand_bank) &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(nand_bank) &= ~EXMC_NPCTL_ECCEN; + } +} + +/*! + \brief get the EXMC ECC value + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t nand_bank) +{ + return (EXMC_NECC(nand_bank)); +} + +/*! + \brief deinitialize EXMC PC card bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_deinit(void) +{ + /* EXMC_BANK3_PCCARD */ + EXMC_NPCTL3 = BANK3_NPCTL_RESET; + EXMC_NPINTEN3 = BANK3_NPINTEN_RESET; + EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET; + EXMC_NPATCFG3 = BANK3_NPATCFG_RESET; + EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; +} + +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )| + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )| + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + +/*! + \brief initialize the struct exmc_pccard_parameter_struct + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the structure with default value */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief enable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_enable(void) +{ + EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_disable(void) +{ + EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief enable EXMC interrupt + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source) +{ + /* NAND bank1, bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) |= interrupt_source; +} + +/*! + \brief disable EXMC interrupt + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~interrupt_source; +} + +/*! + \brief check EXMC flag is set or not + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC Card bank + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag) +{ + uint32_t status = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + + if ((status & flag) != (uint32_t)flag ){ + /* flag is reset */ + return RESET; + }else{ + /* flag is set */ + return SET; + } +} + +/*! + \brief clear EXMC flag + \param[in] bank: specifie the NAND bank, PCCARD bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] flag: specify get which flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval none +*/ +void exmc_flag_clear(uint32_t bank, uint32_t flag) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~flag; +} + +/*! + \brief check EXMC interrupt flag is set or not + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source) +{ + uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + interrupt_state = (status & (interrupt_source >> INTEN_INTS_OFFSET)); + + interrupt_enable = (status & interrupt_source); + + if ((interrupt_enable) && (interrupt_state)){ + /* interrupt flag is set */ + return SET; + }else{ + /* interrupt flag is reset */ + return RESET; + } +} + +/*! + \brief clear EXMC interrupt flag + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval none +*/ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source) +{ + /* NAND bank1, bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~(interrupt_source >> INTEN_INTS_OFFSET); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c new file mode 100644 index 0000000000..48c220e193 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c @@ -0,0 +1,254 @@ +/*! + \file gd32f10x_exti.c + \brief EXTI driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#include "gd32f10x_exti.h" + +#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none +*/ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = EXTI_REG_RESET_VALUE; + EXTI_EVEN = EXTI_REG_RESET_VALUE; + EXTI_RTEN = EXTI_REG_RESET_VALUE; + EXTI_FTEN = EXTI_REG_RESET_VALUE; + EXTI_SWIEV = EXTI_REG_RESET_VALUE; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling edge trigger + \arg EXTI_TRIG_BOTH: rising edge and falling edge trigger + \param[out] none + \retval none +*/ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN &= ~(uint32_t)linex; + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch(mode){ + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t)linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t)linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch(trig_type){ + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t)linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t)linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t)linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t)linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t)linex; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c new file mode 100644 index 0000000000..629fb44fc4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c @@ -0,0 +1,964 @@ +/*! + \file gd32f10x_fmc.c + \brief FMC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_fmc.h" + +/*! + \brief set the wait state counter value + \param[in] wscnt£ºwait state counter value + \arg WS_WSCNT_0: FMC 0 wait state + \arg WS_WSCNT_1: FMC 1 wait state + \arg WS_WSCNT_2: FMC 2 wait state + \param[out] none + \retval none +*/ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* write the FMC unlock key */ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } + } +} + +/*! + \brief unlock the FMC bank0 operation + this function can be used for all GD32F10x devices. + for GD32F10x_MD and GD32F10x_HD, this function unlocks bank0. + for GD32F10x_XD and GD32F10x_CL with flash no more than 512KB, it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } +} + +/*! + \brief unlock the FMC bank1 operation + this function can be used for GD32F10x_XD and GD32F10x_CL with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_unlock(void) +{ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + /* write the FMC unlock key */ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL0 |= FMC_CTL0_LK; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* set the LK bit */ + FMC_CTL1 |= FMC_CTL1_LK; + } +} + +/*! + \brief lock the FMC bank0 operation + this function can be used for all GD32F10X devices. + for GD32F10x_MD and GD32F10x_HD, this function unlocks bank0. + for GD32F10x_XD and GD32F10x_CL with flash no more than 512KB, it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_lock(void) +{ + /* set the LK bit*/ + FMC_CTL0 |= FMC_CTL0_LK; +} + +/*! + \brief lock the FMC bank1 operation + this function can be used for GD32F10x_XD and GD32F10x_CL with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_lock(void) +{ + /* set the LK bit*/ + FMC_CTL1 |= FMC_CTL1_LK; +} + +/*! + \brief erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > page_address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + }else{ + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL1 |= FMC_CTL1_PER; + FMC_ADDR1 = page_address; + if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + FMC_ADDR0 = page_address; + } + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL1 &= ~FMC_CTL1_PER; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase bank0 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank0 erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief erase bank1 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank1 erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } + + /* wait until OBWEN bit is set by hardware */ + while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL0 &= ~FMC_CTL0_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL0 and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + /* no security protection */ + OB_SPC = (uint16_t)temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if + you want to protect the corresponding pages. meanwhile, sector + macro could used to set specific sector write protected. + one or more parameters can be selected which are shown as below: + \arg OB_WPx(x = 0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t)(~ob_wp); + temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + only one parameter can be selected which is shown as below: + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + + /* start the option byte program */ + FMC_CTL0 |= FMC_CTL0_OBPG; + + OB_SPC = (uint16_t)ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t)temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program option bytes data + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC user option byte + \param[in] none + \param[out] none + \retval the FMC user option byte values +*/ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t)(FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data +*/ +uint16_t ob_data_get(void) +{ + return (uint16_t)(FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value +*/ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get the FMC option byte security protection + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit + \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval none +*/ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (uint32_t)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (uint32_t)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); + }else{ + /* get the staus of interrupt flag */ + ret1 = (uint32_t)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (uint32_t)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval none +*/ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC bank0 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC bank1 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ + fmc_state = FMC_PGERR; + } + } + } + + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank0 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank0_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank1 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank1_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c new file mode 100644 index 0000000000..50ef448cc6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c @@ -0,0 +1,154 @@ +/*! + \file gd32f10x_fwdgt.c + \brief FWDGT driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status){ + return ERROR; + } + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status){ + return ERROR; + } + FWDGT_RLD = RLD_RLD(reload_value); + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(FWDGT_STAT & flag){ + return SET; + } + + return RESET; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c new file mode 100644 index 0000000000..1ffd9d788b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c @@ -0,0 +1,538 @@ +/*! + \file gd32f10x_gpio.c + \brief GPIO driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch(gpio_periph){ + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + case GPIOF: + /* reset GPIOF */ + rcu_periph_reset_enable(RCU_GPIOFRST); + rcu_periph_reset_disable(RCU_GPIOFRST); + break; + case GPIOG: + /* reset GPIOG */ + rcu_periph_reset_enable(RCU_GPIOGRST); + rcu_periph_reset_disable(RCU_GPIOGRST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); + + /* GPIO speed configuration */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t)speed; + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for(i = 0U;i < 8U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for(i = 8U;i < 16U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) +{ + if(RESET != bit_value){ + GPIO_BOP(gpio_periph) = (uint32_t)pin; + }else{ + GPIO_BC(gpio_periph) = (uint32_t)pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph,uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t)data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t)(GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) +{ + if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t)GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP2: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN_PARTIAL_REMAP: CAN partial remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_CAN_FULL_REMAP: CAN full remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(only for GD32F10X_CL devices) + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping(only for GD32F10X_CL devices) + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping(only for GD32F10X_CL devices and GD32F10X_HD devices) + \arg GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ENET_REMAP: ENET remapping(only for GD32F10X_CL devices) + \arg GPIO_CAN1_REMAP: CAN1 remapping(only for GD32F10X_CL devices) + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping(only for GD32F10X_CL, GD32F10X_HD and GD32F10X_XD devices) + \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping(only for GD32F10X_CL devices) + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32F10X_CL devices) + \arg GPIO_TIMER8_REMAP: TIMER8 remapping + \arg GPIO_TIMER9_REMAP: TIMER9 remapping + \arg GPIO_TIMER10_REMAP: TIMER10 remapping + \arg GPIO_TIMER12_REMAP: TIMER12 remapping + \arg GPIO_TIMER13_REMAP: TIMER13 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){ + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + }else{ + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + }else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){ + remap2 = ((uint32_t)0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + }else{ + temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if(DISABLE != newvalue){ + temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U)); + } + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){ + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + }else{ + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +/*! + \brief select GPIO pin exti sources + \param[in] gpio_outputport: gpio event output port + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOF: output port source F + \arg GPIO_PORT_SOURCE_GPIOG: output port source G + \param[in] gpio_outputpin: GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if(GPIO_PIN_SOURCE_4 > output_pin){ + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_8 > output_pin){ + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_12 > output_pin){ + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else{ + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \arg GPIO_EVENT_PORT_GPIOE: event output port F + \arg GPIO_EVENT_PORT_GPIOE: event output port G + \param[in] output_pin: + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); + + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t)output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + GPIO_LOCK(gpio_periph) = (uint32_t)pin; + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} + +#ifdef GD32F10X_CL +/*! + \brief select ethernet MII or RMII PHY + \param[in] gpio_enetsel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t gpio_enetsel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)gpio_enetsel; +} +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c new file mode 100644 index 0000000000..d823d31d46 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c @@ -0,0 +1,714 @@ +/*! + \file gd32f10x_i2c.c + \brief I2C driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-04-16, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_i2c.h" + +/* I2C register bit mask */ +#define I2CCLK_MAX ((uint32_t)0x00000036U) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_deinit(uint32_t i2c_periph) +{ + switch(i2c_periph){ + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + \param[in] dutycyc: duty cycle in fast mode + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none +*/ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) +{ + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if(100000U >= clkspeed){ + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t)((pclk1/1000000U)+1U); + if(risetime >= I2CCLK_MAX){ + I2C_RT(i2c_periph) = I2CCLK_MAX; + }else if(risetime <= I2CCLK_MIN){ + I2C_RT(i2c_periph) = I2CCLK_MIN; + }else{ + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t)(pclk1/(clkspeed*2U)); + if(clkc < 0x04U){ + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + }else{ + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none +*/ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none +*/ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if(I2C_SMBUS_HOST == type){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none +*/ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none +*/ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) +{ + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received +*/ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none +*/ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none +*/ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none +*/ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none +*/ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none +*/ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecstate: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none +*/ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none +*/ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value +*/ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>>STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none +*/ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none +*/ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none +*/ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c new file mode 100644 index 0000000000..74d740481d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c @@ -0,0 +1,186 @@ +/*! + \file gd32f10x_misc.c + \brief MISC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_misc.h" + +/*! + \brief set the priority group + \param[in] nvic_prigroup: the NVIC priority group + \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \param[out] none + \retval none +*/ +void nvic_priority_group_set(uint32_t nvic_prigroup) +{ + /* set the priority group value */ + SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; +} + +/*! + \brief enable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set + \param[in] nvic_irq_sub_priority: the subpriority needed to set + \param[out] none + \retval none +*/ +void nvic_irq_enable(uint8_t nvic_irq, + uint8_t nvic_irq_pre_priority, + uint8_t nvic_irq_sub_priority) +{ + uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; + + /* use the priority group value to get the temp_pre and the temp_sub */ + switch ((SCB->AIRCR) & (uint32_t)0x700U) { + case NVIC_PRIGROUP_PRE0_SUB4: + temp_pre = 0U; + temp_sub = 0x4U; + break; + case NVIC_PRIGROUP_PRE1_SUB3: + temp_pre = 1U; + temp_sub = 0x3U; + break; + case NVIC_PRIGROUP_PRE2_SUB2: + temp_pre = 2U; + temp_sub = 0x2U; + break; + case NVIC_PRIGROUP_PRE3_SUB1: + temp_pre = 3U; + temp_sub = 0x1U; + break; + case NVIC_PRIGROUP_PRE4_SUB0: + temp_pre = 4U; + temp_sub = 0x0U; + break; + default: + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre = 2U; + temp_sub = 0x2U; + break; + } + + /* get the temp_priority to fill the NVIC->IP register */ + temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); + temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority = temp_priority << 0x04U; + NVIC->IP[nvic_irq] = (uint8_t)temp_priority; + + /* enable the selected IRQ */ + NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief disable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void nvic_irq_disable(uint8_t nvic_irq) +{ + /* disable the selected IRQ.*/ + NVIC->ICER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief set the NVIC vector table base address + \param[in] nvic_vict_tab: the RAM or FLASH base address + \arg NVIC_VECTTAB_RAM: RAM base address + \are NVIC_VECTTAB_FLASH: Flash base address + \param[in] offset: Vector Table offset + \param[out] none + \retval none +*/ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) +{ + SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); +} + +/*! + \brief set the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + by all the enable and disable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_set(uint8_t lowpower_mode) +{ + SCB->SCR |= (uint32_t)lowpower_mode; +} + +/*! + \brief reset the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + woke up by the enable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_reset(uint8_t lowpower_mode) +{ + SCB->SCR &= (~(uint32_t)lowpower_mode); +} + +/*! + \brief set the systick clock source + \param[in] systick_clksource: the systick clock source needed to choose + \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK + \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 + \param[out] none + \retval none +*/ + +void systick_clksource_set(uint32_t systick_clksource) +{ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + /* set the systick clock source from HCLK */ + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + }else{ + /* set the systick clock source from HCLK/8 */ + SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c new file mode 100644 index 0000000000..42d557f374 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c @@ -0,0 +1,282 @@ +/*! + \file gd32f10x_pmu.c + \brief PMU driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-11-26, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_pmu.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + only one parameter can be selected which is shown as below: + \arg PMU_LVDT_0: voltage threshold is 2.2V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.5V + \arg PMU_LVDT_4: voltage threshold is 2.6V + \arg PMU_LVDT_5: voltage threshold is 2.7V + \arg PMU_LVDT_6: voltage threshold is 2.8V + \arg PMU_LVDT_7: voltage threshold is 2.9V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo: + only one parameter can be selected which is shown as below: + \arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + static uint32_t reg_snap[ 4 ]; + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + reg_snap[0] = REG32(0xE000E010U); + reg_snap[1] = REG32(0xE000E100U); + reg_snap[2] = REG32(0xE000E104U); + reg_snap[3] = REG32(0xE000E108U); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF83DU; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFFFFFU; + + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + __SEV(); + __WFE(); + __WFE(); + } + + REG32(0xE000E010U) = reg_snap[0] ; + REG32(0xE000E100U) = reg_snap[1] ; + REG32(0xE000E104U) = reg_snap[2] ; + REG32(0xE000E108U) = reg_snap[3] ; + + /* reset sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief enable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief get flag state + \param[in] flag: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c new file mode 100644 index 0000000000..07010878dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c @@ -0,0 +1,1193 @@ +/*! + \file gd32f10x_rcu.c + \brief RCU driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) +#define SEL_HXTAL ((uint16_t)1U) +#define SEL_PLL ((uint16_t)2U) + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0xFFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x3FFFFFFU) + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset CTL register */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + RCU_CTL &= ~RCU_CTL_HXTALBPS; +#ifdef GD32F10X_CL + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); +#endif /* GD32F10X_CL */ + + /* reset CFG0 register */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | + RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2); +#elif defined(GD32F10X_CL) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4); +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* reset INT and CFG1 register */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_INT = 0x009f0000U; +#elif defined(GD32F10X_CL) + RCU_INT = 0x00ff0000U; + RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | + RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL); +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF: alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCxRST (x=0,1,2, ADC2 is not available for CL series): reset ADC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCxRST (x=0,1,2, ADC2 is not available for CL series): reset ADC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL2 selected + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the CKOUT0SRC, set according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL_MULx (XD series x = 2..32, CL series x = 2..14, 6.5, 16..32) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +/*! + \brief configure the PREDV0 division factor + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1,2 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + /* reset PREDV0 bit */ + reg &= ~RCU_CFG0_PREDV0; + if(RCU_PREDV0_DIV2 == predv0_div){ + /* set the PREDV0 bit */ + reg |= RCU_CFG0_PREDV0; + } + + RCU_CFG0 = reg; +} +#elif defined(GD32F10X_CL) +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << 14); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; +} + +/*! + \brief configure the USBD/USBFS prescaler factor + \param[in] usb_psc: USB prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKUSB_CKPLL_DIV1_5: USBD/USBFS prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBD/USBFS prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBD/USBFS prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBD/USBFS prescaler select CK_PLL/2 + \param[out] none + \retval none +*/ +void rcu_usb_clock_config(uint32_t usb_psc) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* configure the USBD/USBFS prescaler factor */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + reg &= ~RCU_CFG0_USBDPSC; +#elif defined(GD32F10X_CL) + reg &= ~RCU_CFG0_USBFSPSC; +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + RCU_CFG0 = (reg | usb_psc); +} + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +#ifdef GD32F10X_CL +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} +#endif /* GD32F10X_CL */ + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only) + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only) + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization interrupt and ckm flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) +{ + RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + Only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + +#ifdef GD32F10X_CL + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; +#endif /* GD32F10X_CL */ + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F10X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F10X_CL */ + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F10X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F10X_CL */ + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V + \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp; +#ifdef GD32F10X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F10X_CL */ + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE/2U; + } +#elif defined(GD32F10X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F10X_HD and GD32F10X_XD */ + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + + cksys_freq = ck_src * pllmf; + + #ifdef GD32F10X_CL + if(15U == pllmf){ + /* PLL source clock multiply by 6.5 */ + cksys_freq = ck_src * 6U + ck_src / 2U; + } + #endif /* GD32F10X_CL */ + + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c new file mode 100644 index 0000000000..86768e0989 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c @@ -0,0 +1,276 @@ +/*! + \file gd32f10x_rtc.c + \brief RTC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_rtc.h" + +/* RTC register high / low bits mask */ +#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */ +#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */ + +/* RTC register high bits offset */ +#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U) + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET); + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET); + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET); + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + + temp = RTC_CNTL; + temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); + return temp; +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + + temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET); + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief get RTC interrupt flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_interrupt_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC interrupt flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval none +*/ +void rtc_interrupt_flag_clear(uint32_t flag) +{ + /* clear RTC interrupt flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c new file mode 100644 index 0000000000..7a8ed96f13 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c @@ -0,0 +1,813 @@ +/*! + \file gd32f10x_sdio.c + \brief SDIO driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_sdio.h" + +#define DEFAULT_RESET_VALUE 0x00000000U + +/*! + \brief deinitialize the SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_deinit(void) +{ + SDIO_PWRCTL = DEFAULT_RESET_VALUE; + SDIO_CLKCTL = DEFAULT_RESET_VALUE; + SDIO_CMDAGMT = DEFAULT_RESET_VALUE; + SDIO_CMDCTL = DEFAULT_RESET_VALUE; + SDIO_DATATO = DEFAULT_RESET_VALUE; + SDIO_DATALEN = DEFAULT_RESET_VALUE; + SDIO_DATACTL = DEFAULT_RESET_VALUE; + SDIO_INTC = DEFAULT_RESET_VALUE; + SDIO_INTEN = DEFAULT_RESET_VALUE; +} + +/*! + \brief configure the SDIO clock + \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: + \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK + \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK + \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass + \arg SDIO_CLOCKBYPASS_DISABLE: no bypass + \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle + \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on + \param[in] clock_division: clock division, less than 256 + \param[out] none + \retval none +*/ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division) +{ + uint32_t clock_config = 0U; + clock_config = SDIO_CLKCTL; + /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ + clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV); + + /* configure the SDIO_CLKCTL according to the parameters */ + clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division); + SDIO_CLKCTL = clock_config; +} + +/*! + \brief enable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief disable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief set different SDIO card bus mode + \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: + \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode + \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode + \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode + \param[out] none + \retval none +*/ +void sdio_bus_mode_set(uint32_t bus_mode) +{ + /* reset the SDIO card bus mode bits and set according to bus_mode */ + SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE; + SDIO_CLKCTL |= bus_mode; +} + +/*! + \brief set the SDIO power state + \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off + \param[out] none + \retval none +*/ +void sdio_power_state_set(uint32_t power_state) +{ + SDIO_PWRCTL = power_state; +} + +/*! + \brief get the SDIO power state + \param[in] none + \param[out] none + \retval SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off +*/ +uint32_t sdio_power_state_get(void) +{ + return SDIO_PWRCTL; +} + +/*! + \brief enable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN; +} + +/*! + \brief disable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN; +} + +/*! + \brief configure the command and response + \param[in] cmd_index: command index, refer to the related specifications + \param[in] cmd_argument: command argument, refer to the related specifications + \param[in] response_type: response type + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSETYPE_NO: no response + \arg SDIO_RESPONSETYPE_SHORT: short response + \arg SDIO_RESPONSETYPE_LONG: long response + \param[out] none + \retval none +*/ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) +{ + uint32_t cmd_config = 0U; + /* reset the command index, command argument and response type */ + SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; + SDIO_CMDAGMT = cmd_argument; + cmd_config = SDIO_CMDCTL; + cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP); + /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */ + cmd_config |= (cmd_index | response_type); + SDIO_CMDCTL = cmd_config; +} + +/*! + \brief set the command state machine wait type + \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: + \arg SDIO_WAITTYPE_NO: not wait interrupt + \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt + \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer + \param[out] none + \retval none +*/ +void sdio_wait_type_set(uint32_t wait_type) +{ + /* reset INTWAIT and WAITDEND */ + SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND); + /* set the wait type according to wait_type */ + SDIO_CMDCTL |= wait_type; +} + +/*! + \brief enable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN; +} + +/*! + \brief disable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; +} + +/*! + \brief get the last response command index + \param[in] none + \param[out] none + \retval last response command index +*/ +uint8_t sdio_command_index_get(void) +{ + return (uint8_t)SDIO_RSPCMDIDX; +} + +/*! + \brief get the response for the last received command + \param[in] responsex: SDIO response + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] + \arg SDIO_RESPONSE1: card response[95:64] + \arg SDIO_RESPONSE2: card response[63:32] + \arg SDIO_RESPONSE3: card response[31:1], plus bit 0 + \param[out] none + \retval response for the last received command +*/ +uint32_t sdio_response_get(uint32_t responsex) +{ + uint32_t resp_content = 0U; + switch(responsex){ + case SDIO_RESPONSE0: + resp_content = SDIO_RESP0; + break; + case SDIO_RESPONSE1: + resp_content = SDIO_RESP1; + break; + case SDIO_RESPONSE2: + resp_content = SDIO_RESP2; + break; + case SDIO_RESPONSE3: + resp_content = SDIO_RESP3; + break; + default: + break; + } + return resp_content; +} + +/*! + \brief configure the data timeout, data length and data block size + \param[in] data_timeout: data timeout period in card bus clock periods + \param[in] data_length: number of data bytes to be transferred + \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: + \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte + \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes + \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes + \arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes + \arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes + \arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes + \arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes + \arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes + \arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes + \arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes + \arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes + \arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes + \arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes + \arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes + \arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes + \param[out] none + \retval none +*/ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize) +{ + /* reset data timeout, data length and data block size */ + SDIO_DATATO &= ~SDIO_DATATO_DATATO; + SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN; + SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ; + /* configure the related parameters of data */ + SDIO_DATATO = data_timeout; + SDIO_DATALEN = data_length; + SDIO_DATACTL |= data_blocksize; +} + +/*! + \brief configure the data transfer mode and direction + \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSMODE_BLOCK: block transfer + \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer + \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSDIRECTION_TOCARD: write data to card + \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card + \param[out] none + \retval none +*/ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction) +{ + uint32_t data_trans = 0U; + /* reset the data transfer mode, transfer direction and set according to the parameters */ + data_trans = SDIO_DATACTL; + data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR); + data_trans |= (transfer_mode | transfer_direction); + SDIO_DATACTL = data_trans; +} + +/*! + \brief enable the DSM(data state machine) for data transfer + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DATAEN; +} + +/*! + \brief disable the DSM(data state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN; +} + +/*! + \brief write data(one word) to the transmit FIFO + \param[in] data: 32-bit data write to card + \param[out] none + \retval none +*/ +void sdio_data_write(uint32_t data) +{ + SDIO_FIFO = data; +} + +/*! + \brief read data(one word) from the receive FIFO + \param[in] none + \param[out] none + \retval received data +*/ +uint32_t sdio_data_read(void) +{ + return SDIO_FIFO; +} + +/*! + \brief get the number of remaining data bytes to be transferred to card + \param[in] none + \param[out] none + \retval number of remaining data bytes to be transferred +*/ +uint32_t sdio_data_counter_get(void) +{ + return SDIO_DATACNT; +} + +/*! + \brief get the number of words remaining to be written or read from FIFO + \param[in] none + \param[out] none + \retval remaining number of words +*/ +uint32_t sdio_fifo_counter_get(void) +{ + return SDIO_FIFOCNT; +} + +/*! + \brief enable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DMAEN; +} + +/*! + \brief disable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN; +} + +/*! + \brief get the flags state of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_CMDRUN: command transmission in progress flag + \arg SDIO_FLAG_TXRUN: data transmission in progress flag + \arg SDIO_FLAG_RXRUN: data reception in progress flag + \arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO + \arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO + \arg SDIO_FLAG_TFF: transmit FIFO is full flag + \arg SDIO_FLAG_RFF: receive FIFO is full flag + \arg SDIO_FLAG_TFE: transmit FIFO is empty flag + \arg SDIO_FLAG_RFE: receive FIFO is empty flag + \arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag + \arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_flag_get(uint32_t flag) +{ + FlagStatus temp_flag = RESET; + if(RESET != (SDIO_STAT & flag)){ + temp_flag = SET; + } + return temp_flag; +} + +/*! + \brief clear the pending flags of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_flag_clear(uint32_t flag) +{ + SDIO_INTC = flag; +} + +/*! + \brief enable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_enable(uint32_t int_flag) +{ + SDIO_INTEN |= int_flag; +} + +/*! + \brief disable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_disable(uint32_t int_flag) +{ + SDIO_INTEN &= ~int_flag; +} + +/*! + \brief get the interrupt flags state of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state = 0U; + state = SDIO_STAT; + if(state & int_flag){ + state = SDIO_INTEN; + /* check whether the corresponding bit in SDIO_INTEN is set or not */ + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear the interrupt pending flags of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_interrupt_flag_clear(uint32_t int_flag) +{ + SDIO_INTC = int_flag; +} + +/*! + \brief enable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWEN; +} + +/*! + \brief disable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWEN; +} + +/*! + \brief enable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWSTOP; +} + +/*! + \brief disable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP; +} + +/*! + \brief set the read wait type(SD I/O only) + \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: + \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK + \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] + \param[out] none + \retval none +*/ +void sdio_readwait_type_set(uint32_t readwait_type) +{ + if(SDIO_READWAITTYPE_CLK == readwait_type){ + SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; + }else{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; + } +} + +/*! + \brief enable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_IOEN; +} + +/*! + \brief disable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_IOEN; +} + +/*! + \brief enable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief disable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief enable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN; +} + +/*! + \brief disable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN; +} + +/*! + \brief enable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_enable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN; +} + +/*! + \brief disable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_disable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN; +} + +/*! + \brief enable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief disable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c new file mode 100644 index 0000000000..6cb4a22dec --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c @@ -0,0 +1,717 @@ +/*! + \file gd32f10x_spi.c + \brief SPI driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_spi.h" + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */ + +/* default value and offset */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */ +#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ +#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with the default values + \param[in] spi_struct: SPI parameter stuct + \param[out] none + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct* spi_struct) +{ + /* set the SPI struct with the default values */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl) +{ + uint32_t reg = 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)mode; + /* select I2S standard */ + reg |= (uint32_t)standard; + /* select I2S polarity */ + reg |= (uint32_t)ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + +#ifdef GD32F10X_CL + /* get the I2S clock source */ + if(SPI1 == ((uint32_t)spi_periph)){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET); + + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 14 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); + /* calculate I2S clock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } +#else + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); +#endif /* GD32F10X_CL */ + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* configure SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \param[out] none + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly) +{ + /* enable SPI CRC */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if((0U != reg1) && (0U != reg2)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + one or more parameters can be selected which are shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(RESET != (SPI_STAT(spi_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c new file mode 100644 index 0000000000..bff7bfe1e7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c @@ -0,0 +1,2003 @@ +/*! + \file gd32f10x_timer.c + \brief TIMER driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_timer.h" + +/* TIMER init parameter mask */ +#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ +#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ +#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ + +/*! + \brief deinit a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + case TIMER7: + /* reset TIMER7 */ + rcu_periph_reset_enable(RCU_TIMER7RST); + rcu_periph_reset_disable(RCU_TIMER7RST); + break; +#ifdef GD32F10X_XD + case TIMER8: + /* reset TIMER8 */ + rcu_periph_reset_enable(RCU_TIMER8RST); + rcu_periph_reset_disable(RCU_TIMER8RST); + break; + case TIMER9: + /* reset TIMER9 */ + rcu_periph_reset_enable(RCU_TIMER9RST); + rcu_periph_reset_disable(RCU_TIMER9RST); + break; + case TIMER10: + /* reset TIMER10 */ + rcu_periph_reset_enable(RCU_TIMER10RST); + rcu_periph_reset_disable(RCU_TIMER10RST); + break; + case TIMER11: + /* reset TIMER11 */ + rcu_periph_reset_enable(RCU_TIMER11RST); + rcu_periph_reset_disable(RCU_TIMER11RST); + break; + case TIMER12: + /* reset TIMER12 */ + rcu_periph_reset_enable(RCU_TIMER12RST); + rcu_periph_reset_disable(RCU_TIMER12RST); + break; + case TIMER13: + /* reset TIMER13 */ + rcu_periph_reset_enable(RCU_TIMER13RST); + rcu_periph_reset_disable(RCU_TIMER13RST); + break; +#endif /* GD32F10X_XD */ + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock,0~65535 + alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP, + TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN + period: counter auto reload value,0~65535 + clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) || + (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || + (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)){ + TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); + } + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] prescaler: prescaler value + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] repetition: the counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] autoreload: the counter auto-reload value + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] counter: the counter value + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..8,11) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow, + or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: timer DMA source enable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: timer DMA source disable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA disable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request disable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA disable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: please refer to the following parameters + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: please refer to the following parameters + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_BRKG: break event generation, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) | + ((uint32_t)(breakpara->ideloffstate)) | + ((uint32_t)(breakpara->deadtime)) | + ((uint32_t)(breakpara->breakpolarity)) | + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode)) | + ((uint32_t)(breakpara->breakstate))) ; +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief enable or disable TIMER primary output function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 4U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 2U); + } + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 8U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 4U); + } + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 12U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 6U); + } + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM0 mode + \arg TIMER_OC_MODE_PWM1: PWM1 mode + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] pulse: channel output pulse value + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \arg TIMER_CH_3: TIMER channel3 + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING, + TIMER_IC_POLARITY_BOTH_EDGE(only for TIMER1~TIMER8) + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI, + TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, + TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,channel,(uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + case TIMER_CH_0: + /* read TIMER channel 0 capture compare register value */ + count_value = TIMER_CH0CV(timer_periph); + break; + case TIMER_CH_1: + /* read TIMER channel 1 capture compare register value */ + count_value = TIMER_CH1CV(timer_periph); + break; + case TIMER_CH_2: + /* read TIMER channel 2 capture compare register value */ + count_value = TIMER_CH2CV(timer_periph); + break; + case TIMER_CH_3: + /* read TIMER channel 3 capture compare register value */ + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \param[in] icpwm:TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity)<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection)<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: please refer to the following parameters + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channel 0 as trigger output TRGO(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4,7)) + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) +{ + /* configure the quadrature decoder mode */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + /* configure input capture selection */ + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + /* configure channel input capture polarity */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph,intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph,extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt source disable + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c new file mode 100644 index 0000000000..c1f000a6f0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c @@ -0,0 +1,766 @@ +/*! + \file gd32f10x_usart.c + \brief USART driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.1, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_usart.h" + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & (0x0000fff0U); + fradiv = udiv & (0x0000000fU); + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg ; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: disable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure receiver mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint16_t data) +{ + USART_DATA(usart_periph) = USART_DATA_DATA & data; +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] gaut: guard time value + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut)<<8)); +} + +/*! + \brief enable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_SCEN; +} + +/*! + \brief disable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); +} + +/*! + \brief enable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_NKEN; +} + +/*! + \brief disable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); +} + +/*! + \brief enable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_irda_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_IREN; +} + +/*! + \brief disable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_irda_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); +} + +/*! + \brief configure the peripheral clock prescaler in USART IrDA low-power mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] psc: 0x00-0xFF + \param[out] none + \retval none +*/ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) +{ + USART_GP(usart_periph) &= ~(USART_GP_PSC); + USART_GP(usart_periph) |= psc; +} + +/*! + \brief configure IrDA low-power + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] irlp: IrDA low-power or normal + only one parameter can be selected which is shown as below: + \arg USART_IRLP_LOW: low-power + \arg USART_IRLP_NORMAL: normal + \param[out] none + \retval none +*/ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); + USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); +} + +/*! + \brief configure hardware flow control RTS + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] rtsconfig: enable or disable RTS + only one parameter can be selected which is shown as below: + \arg USART_RTS_ENABLE: enable RTS + \arg USART_RTS_DISABLE: disable RTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_RTSEN; + ctl |= rtsconfig; + /* configure RTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure hardware flow control CTS + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] ctsconfig: enable or disable CTS + only one parameter can be selected which is shown as below: + \arg USART_CTS_ENABLE: enable CTS + \arg USART_CTS_DISABLE: disable CTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_CTSEN; + ctl |= ctsconfig; + /* configure CTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA reception + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3) + \param[in] dmacmd: enable or disable DMA for reception + only one parameter can be selected which is shown as below: + \arg USART_DENR_ENABLE: DMA enable for reception + \arg USART_DENR_DISABLE: DMA disable for reception + \param[out] none + \retval none +*/ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENR; + ctl |= dmacmd; + /* configure DMA reception */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA transmission + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3) + \param[in] dmacmd: enable or disable DMA for transmission + only one parameter can be selected which is shown as below: + \arg USART_DENT_ENABLE: DMA enable for transmission + \arg USART_DENT_DISABLE: DMA disable for transmission + \param[out] none + \retval none +*/ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENT; + ctl |= dmacmd; + /* configure DMA transmission */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief get flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTSF: CTS change flag + \arg USART_FLAG_LBDF: LIN break detected flag + \arg USART_FLAG_TBE: transmit data buffer empty + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_IDLEF: IDLE frame detected flag + \arg USART_FLAG_ORERR: overrun error + \arg USART_FLAG_NERR: noise error flag + \arg USART_FLAG_FERR: frame error flag + \arg USART_FLAG_PERR: parity error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) +{ + if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTSF: CTS change flag + \arg USART_FLAG_LBDF: LIN break detected flag + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \param[out] none + \retval none +*/ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) +{ + USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); +} + +/*! + \brief enable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \param[out] none + \retval none +*/ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief disable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \param[out] none + \retval none +*/ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief get USART interrupt and flag status + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_PERR: parity error interrupt and flag + \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag + \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error + \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag + \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U; + /* get the interrupt enable bit status */ + intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); + + if(flagstatus && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear USART interrupt flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART interrupt flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_CTS: CTS change flag + \arg USART_INT_FLAG_LBD: LIN break detected flag + \arg USART_INT_FLAG_TC: transmission complete + \arg USART_INT_FLAG_RBNE: read data buffer not empty + \param[out] none + \retval none +*/ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag) +{ + USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c new file mode 100644 index 0000000000..ce9ffc57e7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c @@ -0,0 +1,149 @@ +/*! + \file gd32f10x_wwdgt.c + \brief WWDGT driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_wwdgt.h" + +/* write value to WWDGT_CTL_CNT bit field */ +#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) +/* write value to WWDGT_CFG_WIN bit field */ +#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/*! + \brief reset the window watchdog timer configuration + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_deinit(void) +{ + rcu_periph_reset_enable(RCU_WWDGTRST); + rcu_periph_reset_disable(RCU_WWDGTRST); +} + +/*! + \brief start the window watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_enable(void) +{ + WWDGT_CTL |= WWDGT_CTL_WDGTEN; +} + +/*! + \brief configure the window watchdog timer counter value + \param[in] counter_value: 0x00 - 0x7F + \param[out] none + \retval none +*/ +void wwdgt_counter_update(uint16_t counter_value) +{ + uint32_t reg = 0U; + + reg = (WWDGT_CTL & (~WWDGT_CTL_CNT)); + reg |= CTL_CNT(counter_value); + + WWDGT_CTL = reg; +} + +/*! + \brief configure counter value, window value, and prescaler divider value + \param[in] counter: 0x00 - 0x7F + \param[in] window: 0x00 - 0x7F + \param[in] prescaler: wwdgt prescaler value + only one parameter can be selected which is shown as below: + \arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1 + \arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2 + \arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4 + \arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8 + \param[out] none + \retval none +*/ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) +{ + uint32_t reg_cfg = 0U, reg_ctl = 0U; + + /* clear WIN and PSC bits, clear CNT bit */ + reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC))); + reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT)); + + /* configure WIN and PSC bits, configure CNT bit */ + reg_cfg |= CFG_WIN(window); + reg_cfg |= prescaler; + reg_ctl |= CTL_CNT(counter); + + WWDGT_CTL = reg_ctl; + WWDGT_CFG = reg_cfg; +} + +/*! + \brief enable early wakeup interrupt of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_interrupt_enable(void) +{ + WWDGT_CFG |= WWDGT_CFG_EWIE; +} + +/*! + \brief check early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus wwdgt_flag_get(void) +{ + if(WWDGT_STAT & WWDGT_STAT_EWIF){ + return SET; + } + + return RESET; +} + +/*! + \brief clear early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_flag_clear(void) +{ + WWDGT_STAT &= (~WWDGT_STAT_EWIF); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h new file mode 100644 index 0000000000..d6c1e1d480 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h @@ -0,0 +1,261 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)((x) >> 8);(uint8_t)((x) >> 16) + +/* audio_freq * data_size (2 bytes) * num_channels (stereo: 2) */ +#define DEFAULT_OUT_BIT_RESOLUTION 16U +#define DEFAULT_OUT_CHANNEL_NBR 2U /* mono = 1, stereo = 2 */ +#define AUDIO_OUT_PACKET (uint32_t)(((USBD_AUDIO_FREQ_16K * \ + (DEFAULT_OUT_BIT_RESOLUTION / 8U) *\ + DEFAULT_OUT_CHANNEL_NBR) / 1000U)) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((AUDIO_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN 109U +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x0001U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_CUR 0x01U + +#define AUDIO_OUT_STREAMING_CTRL 0x02U + +#define PACKET_SIZE(freq) (((freq) * 2U) * 2U / 1000U) + +#define AUDIO_PACKET_SIZE(frq) (uint8_t)(PACKET_SIZE(frq) & 0xFFU), \ + (uint8_t)((PACKET_SIZE(frq) >> 8U) & 0xFFU) + +#define SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq) >> 8U), \ + (uint8_t)((frq) >> 16U) + + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ + uint8_t baInterfaceNr; /*!< interface number of the streaming interfaces */ +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio sub frame */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio sub frame */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + usb_desc_input_terminal in_terminal; + usb_desc_mono_feature_unit feature_unit; + usb_desc_output_terminal out_terminal; + usb_desc_itf std_as_itf_zeroband; + usb_desc_itf std_as_itf_opera; + usb_desc_AS_itf as_itf; + usb_desc_format_type format_typeI; + usb_desc_std_ep std_endpoint; + usb_desc_AS_ep as_endpoint; +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + + uint32_t play_flag; +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class audio_class; + +#endif /* __AUDIO_CORE_H */ + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..6951044bd4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c new file mode 100644 index 0000000000..dd474b151f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c @@ -0,0 +1,549 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "audio_out_itf.h" +#include "audio_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +/* local function prototypes ('static') */ +static uint8_t usbd_audio_sof (usb_dev *udev); +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static void audio_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class audio_class = { + .init = audio_init, + .deinit = audio_deinit, + .req_process = audio_req_handler, + .ctlx_out = audio_ctlx_out, + .data_out = audio_data_out +}; + +usbd_int_cb_struct usb_inthandler = +{ + usbd_audio_sof, +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = 0x0027U, + .bInCollection = 0x01U, + .baInterfaceNr = 0x01U + }, + + .in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x01U, + .wChannelConfig = 0x0000U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = 0x00U, + .iFeature = 0x00U + }, + + .out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, + + .std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x01U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_III, + .bNrChannels = 0x02U, + .bSubFrameSize = 0x02U, + .bBitResolution = 0x10U, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_AUDIO_FREQ_16K, + .bSamFreq[1] = USBD_AUDIO_FREQ_16K >> 8, + .bSamFreq[2] = USBD_AUDIO_FREQ_16K >> 16 + }, + + .std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = PACKET_SIZE(USBD_AUDIO_FREQ_16K), + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static uint8_t* usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + usb_desc_std_ep std_ep = audio_config_set.std_endpoint; + + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_init(udev, EP_BUF_DBL, AUDIO_BUF_ADDR, &ep); + + usbd_int_fops = &usb_inthandler; + + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + udev->ep_transc[AUDIO_OUT_EP][TRANSC_OUT] = audio_class.data_out; + + /* prepare out endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, (uint16_t)AUDIO_OUT_PACKET); + + udev->class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize audio endpoints */ + usbd_ep_deinit(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle the audio class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + usb_transc_config(&udev->transc_in[0], audio->audioctl, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + usb_transc_config(&udev->transc_out[0], audio->audioctl, req->wLength, 0U); + + udev->class_core->req_cmd = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handles the audio out data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void audio_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + if (AUDIO_OUT_EP == ep_num) { + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += AUDIO_OUT_PACKET; + } + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), (uint16_t)AUDIO_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((AUDIO_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } + } +} + +/*! + \brief handles audio control request data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->class_core->req_cmd) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->class_core->req_cmd = 0U; + + audio->audioctl_len = 0U; + } + } + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += AUDIO_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..90d7709694 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c @@ -0,0 +1,242 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + uint8_t status = AUDIO_OK; + + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, (size / 2U)); + audio_state = AUDIO_STATE_PLAYING; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + } + } else { + status = AUDIO_FAIL; + } + break; + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + } + break; + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + } + break; + + /* unsupported command */ + default: + break; + } + + return status; +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + /* call low layer volume setting function */ + if (eval_audio_volume_ctl(vol)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + /* call low layer mute setting function */ + if (eval_audio_mute((uint32_t)cmd)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..9f134ec7b4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h @@ -0,0 +1,164 @@ +/*! + \file cdc_acm_core.h + \brief the header file of CDC ACM driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* CDC subclass code */ +#define USB_CDC_SUBCLASS_DLCM 0x01U +#define USB_CDC_SUBCLASS_ACM 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for PSTN subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#pragma pack(1) + +/* CDC ACM line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +/* header function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +/* call management function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +/* ACM function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +/* union function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +/* configuration descriptor structure */ +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#define USB_CDC_RX_LEN 64U + +typedef struct { + uint8_t pre_packet_send; + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class cdc_class; + +/* function declarations */ +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..6ea6869a20 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c @@ -0,0 +1,509 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CDC_ACM_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = { + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num); +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class cdc_class = { + .req_cmd = NO_CMD, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_process = cdc_acm_req_handler, + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_data_in, + .data_out = cdc_acm_data_out +}; + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive(usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->pre_packet_send = 0U; + + usbd_ep_recev(udev, CDC_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_RX_LEN); +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + uint32_t data_len = cdc->receive_length; + + if ((0U != data_len) && (1U == cdc->packet_sent)) { + cdc->packet_sent = 0U; + usbd_ep_send(udev, CDC_IN_EP, (uint8_t*)(cdc->data), (uint16_t)data_len); + cdc->receive_length = 0U; + } +} + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 otherwise +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->pre_packet_send)) { + return 0U; + } + } + + return 5U; +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(cdc_config_desc.cdc_in_endpoint)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(cdc_config_desc.cdc_cmd_endpoint)); + + udev->ep_transc[EP_ID(CDC_IN_EP)][TRANSC_IN] = cdc_class.data_in; + udev->ep_transc[CDC_OUT_EP][TRANSC_OUT] = cdc_class.data_out; + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 0U; + cdc_handler.packet_sent = 1U; + cdc_handler.pre_packet_send = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200U, + .bCharFormat = 0U, + .bParityType = 0U, + .bDataBits = 0x08U + }; + + udev->class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data endpoints */ + usbd_ep_deinit(udev, CDC_IN_EP); + usbd_ep_deinit(udev, CDC_OUT_EP); + + /* deinitialize the command endpoint */ + usbd_ep_deinit(udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief command data received on control endpoint + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (NO_CMD != udev->class_core->req_cmd) { + cdc->packet_receive = 1U; + cdc->pre_packet_send = 1U; + + udev->class_core->req_cmd = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->transc_in[ep_num]; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (transc->xfer_count == transc->max_len) { + usbd_ep_send(udev, EP_ID(ep_num), NULL, 0U); + } else { + cdc->packet_sent = 1U; + cdc->pre_packet_send = 1U; + } +} + +/*! + \brief handle CDC ACM data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + + cdc->receive_length = udev->transc_out[ep_num].xfer_count; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP, noti_buf[10] = {0U}; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + acm_notification *notif = (void *)noti_buf; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + break; + + case GET_ENCAPSULATED_RESPONSE: + break; + + case SET_COMM_FEATURE: + break; + + case GET_COMM_FEATURE: + break; + + case CLEAR_COMM_FEATURE: + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->class_core->req_cmd = req->bRequest; + + usb_transc_config(&udev->transc_out[0U], (uint8_t *)&cdc->line_coding, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case GET_LINE_CODING: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&cdc->line_coding, 7U, 0U); + + status = REQ_SUPP; + break; + + case SET_CONTROL_LINE_STATE: + notif->bmRequestType = 0xA1U; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wIndex = 0U; + notif->wValue = 0U; + notif->wLength = 2U; + noti_buf[8] = (uint8_t)req->wValue & 3U; + noti_buf[9] = 0U; + + status = REQ_SUPP; + break; + + case SEND_BREAK: + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..7eec7c345d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h @@ -0,0 +1,179 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) do { \ + dfu->bwPollTimeout0 = _BYTE1(x);\ + dfu->bwPollTimeout1 = _BYTE2(x);\ + dfu->bwPollTimeout2 = _BYTE3(x);\ + } while(0) + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) +#define USB_DFU_CONFIG_DESC_SIZE (18U + (9U * USBD_ITF_MAX_NUM)) +#define DFU_DESC_TYPE 0x21U + +/* DFU device state enumeration */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status enumeration */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests enumeration */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +/* USB DFU handler structure */ +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class dfu_class; + +#endif /* __DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..1ee3fe2c79 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c @@ -0,0 +1,675 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "systick.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in (usb_dev *udev); + +/* DFU requests management functions */ +static void dfu_detach (usb_dev *udev, usb_req *req); +static void dfu_dnload (usb_dev *udev, usb_req *req); +static void dfu_upload (usb_dev *udev, usb_req *req); +static void dfu_getstatus (usb_dev *udev, usb_req *req); +static void dfu_clrstatus (usb_dev *udev, usb_req *req); +static void dfu_getstate (usb_dev *udev, usb_req *req); +static void dfu_abort (usb_dev *udev, usb_req *req); + +static void dfu_mode_leave (usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x00U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +/* USB interface string */ +static usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +uint8_t* usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_process = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + fmc_unlock(); + + systick_config(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the USB DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief handle data in stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + fmc_page_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* preform the write operation */ + uint32_t idx = 0U; + + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + if (dfu->data_len & 0x03U) { /* not an aligned data */ + for (idx = dfu->data_len; idx < ((dfu->data_len & 0xFFFCU) + 4U); idx++) { + dfu->buf[idx] = 0xFFU; + } + } + + /* data received are word multiple */ + for (idx = 0U; idx < dfu->data_len; idx += 4U) { + fmc_word_program(addr, *(uint32_t *)(dfu->buf + idx)); + + addr += 4U; + } + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (STATE_DFU_MANIFEST == dfu->bState) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect(udev); + + usbd_connect(udev); + } else { + /* wait for the period of time specified in detach request */ + delay_1ms(4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_out[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->xfer_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + transc->xfer_count = 0U; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + + return; + } + + usb_transc *transc = &udev->transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->xfer_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = (uint8_t *)(addr); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->xfer_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + SET_POLLING_TIMEOUT(FLASH_ERASE_TIMEOUT); + } else { + SET_POLLING_TIMEOUT(FLASH_WRITE_TIMEOUT); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->xfer_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->xfer_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..052100c663 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h @@ -0,0 +1,67 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class custom_hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..c5fb914bf2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h @@ -0,0 +1,66 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send HID report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h new file mode 100644 index 0000000000..c4caf9477d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +} usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..e8e0a41eae --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c @@ -0,0 +1,503 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "custom_hid_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configure descriptor */ +usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +static uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class custom_hid_class = { + .req_cmd = 0xFFU, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + .req_process = custom_hid_req_handler, + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(custom_hid_handler)); + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, HID_TX_ADDR, &(custom_hid_config_desc.hid_epin)); + usbd_ep_init(udev, EP_BUF_SNG, HID_RX_ADDR, &(custom_hid_config_desc.hid_epout)); + + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->ep_transc[EP_ID(CUSTOMHID_IN_EP)][TRANSC_IN] = custom_hid_class.data_in; + udev->ep_transc[EP_ID(CUSTOMHID_OUT_EP)][TRANSC_OUT] = custom_hid_class.data_out; + + udev->class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit(udev, CUSTOMHID_IN_EP); + usbd_ep_deinit(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)customhid_report_descriptor, + USB_MIN(DESC_LEN_REPORT, req->wLength), + 0U); + + status = REQ_SUPP; + } + break; + + case GET_REPORT: + if (2U == req->wLength) { + usb_transc_config(&udev->transc_in[0], hid->data, 2U, 0U); + + status = REQ_SUPP; + } + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], hid->data, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle custom HID data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return; +} + +/*! + \brief handle custom HID data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + if (CUSTOMHID_OUT_EP == ep_num){ + switch (hid->data[0]){ + case 0x11: + if (RESET != hid->data[1]) { + /* turn on led5 */ + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + case 0x12: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + case 0x13: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + case 0x14: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + default: + /* turn off all leds */ + gd_eval_led_off(LED2); + gd_eval_led_off(LED3); + gd_eval_led_off(LED4); + gd_eval_led_off(LED5); + break; + } + + usbd_ep_recev(udev, CUSTOMHID_IN_EP, hid->data, 2U); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..78c878ac9d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c @@ -0,0 +1,427 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, +#ifdef LPM_ENABLED + .bcdUSB = 0x0201U, +#else + .bcdUSB = 0x0200U, +#endif /* LPM_ENABLED */ + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +#ifdef LPM_ENABLED + +/* BOS descriptor */ +uint8_t USBD_BOSDesc[USB_BOS_DESC_LEN] = +{ + 0x05, + USB_DESCTYPE_BOS, + 0x0C, + 0x00, + 0x01, /* 1 device capability descriptor */ + + /* device capability*/ + 0x07, + USB_DEVICE_CAPABITY, + 0x02, + 0x06, /* LPM capability bit set */ + 0x00, + 0x00, + 0x00 +}; + +#endif /* LPM_ENABLED */ + +usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +static uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { +#ifdef LPM_ENABLED + .bos_desc = (uint8_t *)&USBD_BOSDesc, +#endif /* LPM_ENABLED */ + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req); +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num); + +usb_class hid_class = { + .init = hid_init, + .deinit = hid_deinit, + .req_process = hid_req_handler, + .data_in = hid_data_in_handler +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + /* check if USB is configured */ + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(standard_hid_handler)); + + /* initialize TX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(hid_config_desc.hid_epin)); + + udev->ep_transc[EP_ID(HID_IN_EP)][TRANSC_IN] = hid_class.data_in; + + hid_handler.prev_transfer_complete = 1U; + + udev->class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->user_data) { + ((hid_fop_handler *)udev->user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->idle_state, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)hid_report_desc, + USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength), + 0U); + + status = REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)(&(hid_config_desc.hid_vendor)), + USB_MIN(9U, req->wLength), + 0U); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data stage in DATA IN transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if (hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..e1b958ecb3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h @@ -0,0 +1,82 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_DESC_LEN_IAP_REPORT 35U +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U + +typedef void (*app_func) (void); + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +extern usb_desc iap_desc; +extern usb_class iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send(usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..fe41b32434 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c @@ -0,0 +1,596 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "usb_iap_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028BU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev iap_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configure descriptor */ +usb_hid_desc_config_set iap_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x01U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static void iap_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_process = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x3f, /* REPORT_COUNT (63) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x10, /* REPORT_COUNT (16) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len); + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_iap_handler iap_handler; + + /* initialize TX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(iap_config_desc.hid_epin)); + + /* initialize RX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_RX_ADDR, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0, sizeof(usbd_iap_handler)); + + /* prepare receive Data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + udev->ep_transc[EP_ID(IAP_OUT_EP)][TRANSC_OUT] = iap_class.data_out; + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, IAP_IN_EP); + usbd_ep_deinit (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], iap->report_buf, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)iap_report_desc, + USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength), + 0U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch(iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE: + iap_req_optionbyte(udev); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); +} + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload (usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase (usb_dev *udev) +{ + uint32_t i, addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= (uint32_t)iap->report_buf[3] << 8; + iap->base_address |= (uint32_t)iap->report_buf[4] << 16; + iap->base_address |= (uint32_t)iap->report_buf[5] << 24; + + iap->page_count = iap->report_buf[6]; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= (uint32_t)iap->report_buf[8] << 8; + iap->file_length |= (uint32_t)iap->report_buf[9] << 16; + iap->file_length |= (uint32_t)iap->report_buf[10] << 24; + + /* compute last packet size and transfer times */ + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + for (i = 0U; i < iap->page_count; i ++) { + /* call the standard flash erase-page function */ + fmc_page_erase(addr); + + addr += PAGE_SIZE; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_optionbyte (usb_dev *udev) +{ + uint8_t i = 0U; + uint32_t address = 0x1FFFF800U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0] = 0x02U; + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send(udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave (usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} + +/*! + \brief write data to sectors of memory + \param[in] data: data to be written + \param[in] addr: sector address/code + \param[in] len: length of data to be written (in bytes) + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len) +{ + uint32_t index = 0U; + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return; + } + + if (len & 0x03U) {/* not an aligned data */ + for (index = len; index < ((len & 0xFFFCU) + 4U); index++) { + data[index] = 0xFFU; + } + } + + /* data received are word multiple */ + for (index = 0U; index < len; index += 4U) { + fmc_word_program(addr, *(uint32_t *)(data + index)); + addr += 4U; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..8abad3b021 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,129 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +// uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_dev *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_dev *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_dev *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..c9ab389353 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h @@ -0,0 +1,85 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +/* mass storage class-specific request codes */ +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..7f038ec568 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..a992e0182e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..2e84231eba --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,126 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" + +#define SENSE_LIST_DEEPTH 4U + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_dev *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..16516d898a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,283 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_dev *udev); +static void msc_bbb_data_send (usb_dev *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_dev *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_dev *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint16_t rx_len = udev->transc_out[MSC_OUT_EP].xfer_count; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != rx_len) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_dev *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..9f946e5043 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c @@ -0,0 +1,316 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include "usbd_transc.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static void msc_core_in (usb_dev *udev, uint8_t ep_num); +static void msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_process = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev msc_dev_desc = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set msc_config_desc = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static uint8_t usbd_msc_maxlun = 0U; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_msc_handler msc_handler; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(msc_config_desc.msc_epin)); + + /* initialize Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(msc_config_desc.msc_epout)); + + udev->ep_transc[EP_ID(MSC_IN_EP)][TRANSC_IN] = msc_class.data_in; + udev->ep_transc[MSC_OUT_EP][TRANSC_OUT] = msc_class.data_out; + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_deinit (udev, MSC_IN_EP); + usbd_ep_deinit (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + usb_transc_config(&udev->transc_in[0], &usbd_msc_maxlun, 1U, 0U); + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..e7084cdbac --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..b6730b7382 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,728 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun); +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_dev *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + +// if (1U == msc->scsi_disk_pop) { +// usbd_disconnect (udev); +// } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; +// msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h new file mode 100644 index 0000000000..02bca18e1b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h @@ -0,0 +1,73 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +extern usb_desc printer_desc; +extern usb_class printer_class; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c new file mode 100644 index 0000000000..3e91b6b3d5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t Printer_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +static uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req); +static void printer_data_in (usb_dev *udev, uint8_t ep_num); +static void printer_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class printer_class = { + .init = printer_init, + .deinit = printer_deinit, + .req_process = printer_req_handler, + .data_in = printer_data_in, + .data_out = printer_data_out +}; +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data TX/RX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(printer_config_desc.printer_epin)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(printer_config_desc.printer_epout)); + + udev->ep_transc[EP_ID(PRINTER_IN_EP)][TRANSC_IN] = printer_class.data_in; + udev->ep_transc[PRINTER_OUT_EP][TRANSC_OUT] = printer_class.data_out; + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_deinit(udev, PRINTER_IN_EP); + usbd_ep_deinit(udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + switch (req->bRequest) { + case GET_DEVICE_ID: + usb_transc_config(&udev->transc_in[0], Printer_DEVICE_ID, DEVICE_ID_LEN, 0U); + + status = REQ_SUPP; + break; + + case GET_PORT_STATUS: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&g_port_status, 1U, 0U); + + status = REQ_SUPP; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_in (usb_dev *udev, uint8_t ep_num) +{ +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_out (usb_dev *udev, uint8_t ep_num) +{ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h new file mode 100644 index 0000000000..d1f563a39d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h @@ -0,0 +1,211 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usbd_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_BOS_DESC_LEN 0x0CU /*!< USB BOS descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB SETUP packet length */ +#define USB_DEVICE_CAPABITY 0x10U /*!< USB device capabity */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, /*!< USB reserved2 */ + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, /*!< USB reserved4 */ + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronized frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB endpoint descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB endpoint control attributes*/ + USB_EP_ATTR_ISO = 0x1U, /*!< USB endpoint isochronous attributes*/ + USB_EP_ATTR_BULK = 0x2U, /*!< USB endpoint bulk attributes*/ + USB_EP_ATTR_INT = 0x3U /*!< USB endpoint interrupt attributes*/ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< USB endpoint no SYNC attributes*/ +#define USB_EP_ATTR_ASYNC 0x04U /*!< USB endpoint ASYNC attributes*/ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< USB endpoint adaptive attributes*/ +#define USB_EP_ATTR_SYNC 0x0CU /*!< USB endpoint SYNC attributes*/ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< USB endpoint SYNC type attributes*/ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< USB endpoint data attributes*/ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< USB endpoint feedback attributes*/ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< USB endpoint implicit feedback attributes*/ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< USB endpoint usage type attributes*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet definition */ +typedef union _usb_setup { + uint8_t data[8]; /*!< USB setup data */ + + usb_req req; /*!< USB setup request */ +} usb_setup; + +/* USB descriptor definition */ +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t wTotalLength; /*!< size of the configuration descriptor header, and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attribute */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h new file mode 100644 index 0000000000..44ba5c72ce --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h @@ -0,0 +1,333 @@ +/*! + \file usbd_core.h + \brief USB device driver core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "usb_ch9_std.h" + +/* endpoints definitions */ +#define EP_IN(x) ((uint8_t)(0x80U | (x))) +#define EP_OUT(x) ((uint8_t)(x)) + +#define EP_DIR(x) ((uint8_t)((x) >> 7U)) +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) + +/* USB device endpoint0 max packet size */ +#define USBD_EP0_MAX_SIZE 64U + +#define USBD_TRANSC_COUNT 3U + +/* USB device operation status */ +enum usbd_status { + USBD_UNCONNECTED = 0U, /*!< USB device unconnected status */ + USBD_DEFAULT, /*!< USB device default status */ + USBD_ADDRESSED, /*!< USB device addressed status */ + USBD_CONFIGURED, /*!< USB device configured status */ + USBD_SUSPENDED, /*!< USB device suspended status */ + USBD_CONNECTED /*!< USB device connected status */ +}; + +/* USB device operation state */ +enum usbd_state { + USBD_OK = 0U, /*!< USB device OK state */ + USBD_BUSY, /*!< USB device busy state */ + USBD_FAIL /*!< USB device fail state */ +}; + +/* USB device type */ +enum usbd_transc { + TRANSC_SETUP = 0U, /*!< SETUP transaction */ + TRANSC_OUT, /*!< OUT transaction */ + TRANSC_IN, /*!< IN transaction */ + TRANSC_UNKNOWN /*!< unknown transaction */ +}; + +/* USB device endpoint buffer type */ +enum usbd_ep_kind { + EP_BUF_SNG = 0U, /*!< single buffer endpoint type value */ + EP_BUF_DBL /*!< double buffer endpoint type value */ +}; + +/* USB device transaction structure */ +typedef struct { + uint8_t max_len; /*!< packet max length */ + uint8_t ep_stall; /*!< endpoint STALL */ + + uint8_t *xfer_buf; /*!< transfer buffer */ + uint16_t xfer_len; /*!< transfer length */ + uint16_t xfer_count; /*!< transfer count */ +} usb_transc; + +/* USB device basic structure */ +typedef struct { + uint8_t max_ep_count; /*!< endpoint max count */ + uint8_t twin_buf; /*!< double buffer */ + uint16_t ram_size; /*!< ram size */ +} usb_basic; + +/* USB descriptor */ +typedef struct { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + uint8_t **strings; /*!< strings descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t esof_count; /*!< ESOF count */ + uint8_t suspend_enabled; /*!< suspend enabled flag */ + uint8_t remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup enable */ + uint8_t lpm_enable; /*!< LPM enable */ +} usb_pm; + +/* USB LPM management */ +typedef struct { + uint32_t besl; /*!< BESL */ + uint32_t L1_resume; /*!< L1 resume */ + uint32_t L1_remote_wakeup; /*!< L1 remote wakeup */ +} usb_lpm; + +/* USB control information */ +typedef struct { + usb_req req; /*!< USB request */ + uint8_t ctl_zlp; /*!< control zero length packet */ +} usb_control; + +typedef struct _usb_dev usb_dev; +typedef struct _usb_handler usb_handler; +typedef void (*usb_ep_transc) (usb_dev *usbd_dev, uint8_t ep_num); + +/* USB class structure */ +typedef struct { + uint8_t req_cmd; + uint8_t req_altset; + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); + + uint8_t (*req_process) (usb_dev *udev, usb_req *req); + + uint8_t (*ctlx_in) (usb_dev *udev); + uint8_t (*ctlx_out) (usb_dev *udev); + + void (*data_in) (usb_dev *udev, uint8_t ep_num); + void (*data_out) (usb_dev *udev, uint8_t ep_num); +} usb_class; + +/* USB core driver structure */ +struct _usb_dev { + /* basic parameters */ + uint8_t config; + uint8_t dev_addr; + + __IO uint8_t cur_status; + __IO uint8_t backup_status; + + usb_pm pm; +#ifdef LPM_ENABLED + usb_lpm lpm; +#endif /* LPM_ENABLED */ + usb_control control; + + usb_transc transc_out[EP_COUNT]; + usb_transc transc_in[EP_COUNT]; + + usb_ep_transc ep_transc[EP_COUNT][USBD_TRANSC_COUNT]; + + /* device class */ + usb_desc *desc; + usb_class *class_core; + usb_handler *drv_handler; + + void *class_data[USBD_ITF_MAX_NUM]; + void *user_data; + void *data; +}; + +typedef struct +{ + uint8_t (*SOF) (usb_dev *udev); /*!< SOF ISR callback */ +} usbd_int_cb_struct; + +/* USB handler structure */ +struct _usb_handler { + void (*init) (void); + void (*deinit) (void); + + void (*dp_pullup) (FlagStatus status); + void (*set_addr) (usb_dev *udev); + void (*suspend) (void); + void (*suspend_leave) (void); + void (*resume) (usb_dev *udev); + + void (*ep_reset) (usb_dev *udev); + void (*ep_setup) (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); + void (*ep_disable) (usb_dev *udev, uint8_t ep_addr); + void (*ep_rx_enable) (usb_dev *udev, uint8_t ep_num); + void (*ep_write) (uint8_t *fifo, uint8_t ep_num, uint16_t bytes); + uint16_t (*ep_read) (uint8_t *fifo, uint8_t ep_num, uint8_t buf_kind); + void (*ep_stall_set) (usb_dev *udev, uint8_t ep_addr); + void (*ep_stall_clear) (usb_dev *udev, uint8_t ep_addr); + uint8_t (*ep_status_get) (usb_dev *udev, uint8_t ep_addr); +}; + +extern usbd_int_cb_struct *usbd_int_fops; + +/* static inline function definitions */ +/*! + \brief device connect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_connect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(SET); + + udev->cur_status = (uint8_t)USBD_CONNECTED; +} + + +/*! + \brief device disconnect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_disconnect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(RESET); + + udev->cur_status = (uint8_t)USBD_UNCONNECTED; +} + +/*! + \brief device core register configure when stop device + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_core_deinit (usb_dev *udev) +{ + udev->drv_handler->deinit(); +} + +/*! + \brief initialize endpoint + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: buffer address + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_init (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + udev->drv_handler->ep_setup(udev, buf_kind, buf_addr, ep_desc); +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_deinit (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_disable(udev, ep_addr); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_set(udev, ep_addr); +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_clear_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_clear(udev, ep_addr); +} + +/*! + \brief get endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usbd_ep_status_get (usb_dev *udev, uint8_t ep_addr) +{ + return udev->drv_handler->ep_status_get(udev, ep_addr); +} + +/* function declarations */ +/* initialize USBD */ +void usbd_init(usb_dev *udev, usb_desc *desc, usb_class *usbc); +/* endpoint prepare to transmit data */ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); +/* endpoint prepare to receive data */ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h new file mode 100644 index 0000000000..5f0f4e2745 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h @@ -0,0 +1,111 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usb_ch9_std.h" + +#ifndef NULL + #define NULL 0U +#endif + +/* request state enumeration */ +typedef enum _usb_reqsta +{ + REQ_SUPP = 0x0U, /* supported request */ + REQ_NOTSUPP = 0x1U /* unsupported request */ +} usb_reqsta; + +/* string descriptor index enumeration */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ + STR_IDX_MAX = 0x6U /* string index max value */ +}; + +/* PWR status enumeration */ +typedef enum +{ + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +/* USB endpoint feature enumeration */ +typedef enum +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* device unique ID */ +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) /* device ID information */ + +//#define USB_SERIAL_STRING_SIZE 0x1AU + +/* USB device exported macros */ +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req); +/* handle device class request */ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h new file mode 100644 index 0000000000..dcdb2183bc --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h @@ -0,0 +1,67 @@ +/*! + \file usbd_pwr.h + \brief USB device power management functions prototype + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_PWR_H +#define __USBD_PWR_H + +#include "usbd_core.h" + +/* static inline function definitions */ +/*! + \brief first operation of USB wakeup is to wakeup MCU + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void resume_mcu (usb_dev *udev) +{ + udev->drv_handler->suspend_leave(); +} + +/*! + \brief set USB device to suspend mode + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_to_suspend (usb_dev *udev) +{ + udev->drv_handler->suspend(); +} + +/* function declarations */ +/* start to remote wakeup */ +void usbd_remote_wakeup_active (usb_dev *udev); + +#endif /* __USBD_PWR_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h new file mode 100644 index 0000000000..eb9a8138e1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h @@ -0,0 +1,64 @@ +/*! + \file usbd_transc.h + \brief USBD transaction + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_TRANSC_H +#define __USB_TRANSC_H + +#include "usbd_core.h" + +/*! + \brief USB transaction configure + \param[in] transc: pointer to USB device transaction instance + \param[in] buf: transfer data buffer + \param[in] len: transfer data length + \param[in] count: transfer data counter + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_transc_config (usb_transc *transc, uint8_t *buf, uint16_t len, uint16_t count) +{ + transc->xfer_buf = buf; + transc->xfer_len = len; + transc->xfer_count = count; +} + +/* function declarations */ +/* process USB SETUP transaction */ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num); +/* process USB OUT transaction */ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num); +/* process USB IN transaction */ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num); + +#endif /* __USB_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c new file mode 100644 index 0000000000..6ad4188b2e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c @@ -0,0 +1,127 @@ +/*! + \file usbd_core.c + \brief USB device driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_transc.h" +#include "usbd_lld_core.h" + +usbd_int_cb_struct *usbd_int_fops = NULL; + +/*! + \brief configure USB device initialization + \param[in] udev: pointer to USB core instance + \param[in] desc: pointer to USB descriptor + \param[in] usbc: USB class + \param[out] none + \retval none +*/ +void usbd_init (usb_dev *udev, usb_desc *desc, usb_class *usbc) +{ + /* configure USBD core basic attributes */ + usbd_core.basic.max_ep_count = 8U; + usbd_core.basic.twin_buf = 1U; + usbd_core.basic.ram_size = 512U; + + usbd_core.dev = udev; + + udev->desc = desc; + udev->class_core = usbc; + udev->drv_handler = &usbd_drv_handler; + + udev->ep_transc[0][TRANSC_SETUP] = _usb_setup_transc; + udev->ep_transc[0][TRANSC_OUT] = _usb_out0_transc; + udev->ep_transc[0][TRANSC_IN] = _usb_in0_transc; + + /* configure power management */ + udev->pm.power_mode = (udev->desc->config_desc[7] & 0x40U) >> 5; + + /* enable USB suspend */ + udev->pm.suspend_enabled = 1U; + + /* USB low level initialization */ + udev->drv_handler->init(); + + /* create serial string */ + serial_string_get((uint16_t *)udev->desc->strings[STR_IDX_SERIAL]); +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + /* configure the transaction level parameters */ + usb_transc *transc = &udev->transc_out[EP_ID(ep_addr)]; + + usb_transc_config(transc, pbuf, buf_len, 0U); + + /* enable endpoint to receive */ + udev->drv_handler->ep_rx_enable(udev, ep_addr); +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + uint8_t ep_num = EP_ID(ep_addr); + + usb_transc *transc = &udev->transc_in[ep_num]; + + uint16_t len = USB_MIN(buf_len, transc->max_len); + + /* configure the transaction level parameters */ + udev->drv_handler->ep_write(pbuf, ep_num, len); + + usb_transc_config(transc, pbuf + len, buf_len - len, len); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c new file mode 100644 index 0000000000..1af602b314 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c @@ -0,0 +1,747 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* USB enumeration handle functions */ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req); + +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); + +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); + +/* standard device request handler */ +static usb_reqsta (*_std_dev_req[]) (usb_dev *udev, usb_req *req) = { + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_dev *udev, uint8_t index, uint16_t *len) = { + [USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req) +{ + /* call device request handle function */ + return (*_std_dev_req[req->bRequest]) (udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->class_core->req_process(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user */ + + return REQ_NOTSUPP; +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation */ + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->dev_desc[0]; + + return udev->desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->config_desc[2]; + + return udev->desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + if (NULL != udev->desc->bos_desc) { + (void)index; + + *len = (uint16_t)udev->desc->bos_desc[2] | (uint16_t)((uint16_t)udev->desc->bos_desc[3] << 8); + + return udev->desc->bos_desc; + } else { + *len = 0U; + + return NULL; + } +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval string descriptor +*/ +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + uint8_t* desc = udev->desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + + usb_reqsta req_status = REQ_NOTSUPP; + + static uint8_t status[2] = {0U}; + + switch(req->bmRequestType & USB_RECPTYPE_MASK) { + /* handle device get status request */ + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + if (udev->pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->pm.remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + break; + + default: + break; + } + break; + + /* handle interface get status request */ + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (recp < USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + /* handle endpoint get status request */ + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->transc_out[recp].ep_stall; + } + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], status, 2U, 2U); + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 0U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_clear_stall(udev, ep); + + udev->class_core->req_process(udev, req); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* set endpoint halt feature */ + if (((uint8_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_stall(udev, ep); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->cur_status != (uint8_t)USBD_CONFIGURED) { + if (udev->dev_addr) { + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->transc_in[0]; + + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + if (64U == req->wLength) { + transc->xfer_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + break; + + case USB_DESCTYPE_STR: + if (desc_index < STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, &transc->xfer_len); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->class_core->req_process(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((transc->xfer_len) && (req->wLength)) { + transc->xfer_len = USB_MIN(transc->xfer_len, req->wLength); + + if ((transc->xfer_len < udev->control.req.wLength) && + (0U == transc->xfer_len % transc->max_len)) { + udev->control.ctl_zlp = 1U; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (0U == udev->config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->config) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], &(udev->config), 1U, 1U); + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->class_core->init(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_CONFIGURED; + } + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (0U == config) { + (void)udev->class_core->deinit(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->config) { + /* clear old configuration */ + (void)udev->class_core->deinit(udev, udev->config); + + /* set new configuration */ + udev->config = config; + + (void)udev->class_core->init(udev, config); + } else { + /* no operation */ + } + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + usb_transc_config(&udev->transc_in[0], &(udev->class_core->req_altset), 1U, 1U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + udev->class_core->req_altset = (uint8_t)req->wValue; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: Hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index = 0U; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if (6U != (unicode_str[0] & 0x00FFU)) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if (0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c new file mode 100644 index 0000000000..1713118c36 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c @@ -0,0 +1,60 @@ +/*! + \file usbd_pwr.c + \brief USB device power management driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_pwr.h" + +/*! + \brief start to remote wakeup + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +void usbd_remote_wakeup_active(usb_dev *udev) +{ + resume_mcu(udev); + +#ifdef LPM_ENABLED + if(1U == udev->lpm.L1_remote_wakeup){ + udev->drv_handler->resume(udev); + + udev->lpm.L1_resume = 1U; + } +#endif /* LPM_ENABLED */ + + if(1U == udev->pm.remote_wakeup){ + udev->pm.remote_wakeup_on = 1U; + udev->pm.esof_count = 15U; + udev->drv_handler->resume(udev); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c new file mode 100644 index 0000000000..87563a5cb8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c @@ -0,0 +1,208 @@ +/*! + \file usbd_transc.c + \brief USBD transaction function + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static inline void usb_stall_transc (usb_dev *udev); +static inline void usb_ctl_status_in (usb_dev *udev); +static inline void usb_ctl_data_in (usb_dev *udev); +static inline void usb_ctl_out (usb_dev *udev); +static inline void usb_0len_packet_send (usb_dev *udev); + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + usb_reqsta reqstat = REQ_NOTSUPP; + + uint16_t count = udev->drv_handler->ep_read((uint8_t *)(&udev->control.req), 0U, (uint8_t)EP_BUF_SNG); + + if (count != USB_SETUP_PACKET_LEN) { + usb_stall_transc(udev); + + return; + } + + switch (udev->control.req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request(udev, &udev->control.req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request(udev, &udev->control.req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request(udev, &udev->control.req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == udev->control.req.wLength) { + /* USB control transfer status in stage */ + usb_ctl_status_in(udev); + } else { + if (udev->control.req.bmRequestType & 0x80U) { + usb_ctl_data_in(udev); + } else { + /* USB control transfer data out stage */ + usb_ctl_out(udev); + } + } + } else { + usb_stall_transc(udev); + } +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num) +{ + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_out != NULL)) { + /* device class handle */ + (void)udev->class_core->ctlx_out(udev); + } + + usb_transc_config(&udev->transc_out[ep_num], NULL, 0U, 0U); + + /* enter the control transaction status in stage */ + usb_ctl_status_in(udev); +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + if (udev->control.ctl_zlp) { + /* send 0 length packet */ + usb_0len_packet_send(udev); + + udev->control.ctl_zlp = 0U; + } + + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_in != NULL)) { + (void)udev->class_core->ctlx_in(udev); + } + + /* USB control transfer status out stage */ + usb_ctl_out(udev); + + if (0U != udev->dev_addr) { + udev->drv_handler->set_addr(udev); + + udev->dev_addr = 0U; + } +} + +/*! + \brief USB stalled transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_stall_transc (usb_dev *udev) +{ + usbd_ep_stall(udev, 0x0U); +} + +/*! + \brief USB control transaction status in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_status_in (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} + +/*! + \brief USB control transaction data in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_data_in (usb_dev *udev) +{ + usbd_ep_send(udev, 0U, udev->transc_in[0].xfer_buf, udev->transc_in[0].xfer_len); +} + +/*! + \brief USB control transaction data out & status out stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_out (usb_dev *udev) +{ + udev->drv_handler->ep_rx_enable(udev, 0U); +} + +/*! + \brief USB send 0 length data packet + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_0len_packet_send (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h new file mode 100644 index 0000000000..5963a97a03 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h @@ -0,0 +1,73 @@ +/*! + \file usbd_lld_core.h + \brief USB device low level driver core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_CORE_H +#define __USBD_LLD_CORE_H + +#include "usbd_lld_regs.h" +#include "usbd_core.h" + +/* double buffer endpoint direction enumeration */ +enum dbuf_ep_dir +{ + DBUF_EP_IN, /*!< double buffer in direction */ + DBUF_EP_OUT, /*!< double buffer out direction */ + DBUF_EP_ERR, /*!< double buffer error direction */ +}; + +/* USBD endpoint ram structure */ +typedef struct +{ + __IO uint32_t tx_addr; /*!< transmission address */ + __IO uint32_t tx_count; /*!< transmission count */ + __IO uint32_t rx_addr; /*!< reception address */ + __IO uint32_t rx_count; /*!< reception count */ +} usbd_ep_ram; + +extern struct _usb_handler usbd_drv_handler; + +/* USB core driver structure */ +typedef struct +{ + usb_basic basic; + usb_dev *dev; +} usb_core_drv; + +extern usb_core_drv usbd_core; + +/* function declarations */ +/* free buffer used from application by toggling the SW_BUF byte */ +void user_buffer_free (uint8_t ep_num, uint8_t dir); + +#endif /* __USBD_LLD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h new file mode 100644 index 0000000000..85dbfc3ddd --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h @@ -0,0 +1,48 @@ +/*! + \file usbd_lld_int.h + \brief USB device low level interrupt handler + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_INT_H +#define __USBD_LLD_INT_H + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_pwr.h" + +/* function declarations */ +/* USB device interrupt service routine */ +void usbd_isr (void); +/* handle USB high priority successful transfer event */ +void usbd_int_hpst (usb_dev *udev); + +#endif /* __USBD_LLD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h new file mode 100644 index 0000000000..8773c6a744 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h @@ -0,0 +1,227 @@ +/*! + \file usbd_lld_regs.h + \brief USB device low level registers + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_REGS_H +#define __USBD_LLD_REGS_H + +#include "usbd_conf.h" + +/* USB device registers base address */ +#define USBD USBD_BASE +#define USBD_RAM USBD_RAM_BASE + +/* registers definitions */ +/* common registers */ +#define USBD_CTL (REG32(USBD + 0x40U)) /*!< control register */ +#define USBD_INTF (REG32(USBD + 0x44U)) /*!< interrupt flag register */ +#define USBD_STAT (REG32(USBD + 0x48U)) /*!< status register */ +#define USBD_DADDR (REG32(USBD + 0x4CU)) /*!< device address register */ +#define USBD_BADDR (REG32(USBD + 0x50U)) /*!< buffer address register */ +#define USBD_LPMCS (REG32(USBD + 0x54U)) /*!< USBD LPM control and status register */ + +/* endpoint control and status register */ +#define USBD_EPxCS(ep_num) (REG32(USBD + (ep_num) * 4U)) /*!< endpoint x control and status register address */ + +/* bits definitions */ +/* USBD_CTL */ +#define CTL_STIE BIT(15) /*!< successful transfer interrupt enable mask */ +#define CTL_PMOUIE BIT(14) /*!< packet memory overrun/underrun interrupt enable mask */ +#define CTL_ERRIE BIT(13) /*!< error interrupt enable mask */ +#define CTL_WKUPIE BIT(12) /*!< wakeup interrupt enable mask */ +#define CTL_SPSIE BIT(11) /*!< suspend state interrupt enable mask */ +#define CTL_RSTIE BIT(10) /*!< reset interrupt enable mask */ +#define CTL_SOFIE BIT(9) /*!< start of frame interrupt enable mask */ +#define CTL_ESOFIE BIT(8) /*!< expected start of frame interrupt enable mask */ +#define CTL_L1REQIE BIT(7) /*!< LPM L1 state request interrupt enable */ +#define CTL_L1RSREQ BIT(5) /*!< LPM L1 resume request */ +#define CTL_RSREQ BIT(4) /*!< resume request */ +#define CTL_SETSPS BIT(3) /*!< set suspend state */ +#define CTL_LOWM BIT(2) /*!< low-power mode at suspend state */ +#define CTL_CLOSE BIT(1) /*!< goes to close state */ +#define CTL_SETRST BIT(0) /*!< set USB reset */ + +#ifdef LPM_ENABLED +#define USBD_INTEN BITS(7, 15) /*!< USBD interrupt enable bits */ +#else +#define USBD_INTEN BITS(8, 15) /*!< USBD interrupt enable bits */ +#endif +/* USBD_INTF */ +#define INTF_STIF BIT(15) /*!< successful transfer interrupt flag (read only bit) */ +#define INTF_PMOUIF BIT(14) /*!< packet memory overrun/underrun interrupt flag (clear-only bit) */ +#define INTF_ERRIF BIT(13) /*!< error interrupt flag (clear-only bit) */ +#define INTF_WKUPIF BIT(12) /*!< wakeup interrupt flag (clear-only bit) */ +#define INTF_SPSIF BIT(11) /*!< suspend state interrupt flag (clear-only bit) */ +#define INTF_RSTIF BIT(10) /*!< reset interrupt flag (clear-only bit) */ +#define INTF_SOFIF BIT(9) /*!< start of frame interrupt flag (clear-only bit) */ +#define INTF_ESOFIF BIT(8) /*!< expected start of frame interrupt flag(clear-only bit) */ +#define INTF_L1REQ BIT(7) /*!< LPM L1 transaction is successfully received and acknowledged */ +#define INTF_DIR BIT(4) /*!< direction of transaction (read-only bit) */ +#define INTF_EPNUM BITS(0, 3) /*!< endpoint number (read-only bit) */ + +/* USBD_STAT */ +#define STAT_RXDP BIT(15) /*!< data plus line status */ +#define STAT_RXDM BIT(14) /*!< data minus line status */ +#define STAT_LOCK BIT(13) /*!< locked the USB */ +#define STAT_SOFLN BITS(11, 12) /*!< SOF lost number */ +#define STAT_FCNT BITS(0, 10) /*!< frame number count */ + +/* USBD_DADDR */ +#define DADDR_USBEN BIT(7) /*!< USB module enable */ +#define DADDR_USBADDR BITS(0, 6) /*!< USB device address */ + +/* USBD_EPxCS */ +#define EPxCS_RX_ST BIT(15) /*!< endpoint reception successful transferred */ +#define EPxCS_RX_DTG BIT(14) /*!< endpoint reception data PID toggle */ +#define EPxCS_RX_STA BITS(12, 13) /*!< endpoint reception status bits */ +#define EPxCS_SETUP BIT(11) /*!< endpoint setup transaction completed */ +#define EPxCS_CTL BITS(9, 10) /*!< endpoint type control */ +#define EPxCS_KCTL BIT(8) /*!< endpoint kind control */ +#define EPxCS_TX_ST BIT(7) /*!< endpoint transmission successful transfer */ +#define EPxCS_TX_DTG BIT(6) /*!< endpoint transmission data toggle */ +#define EPxCS_TX_STA BITS(4, 5) /*!< endpoint transmission transfers status bits */ +#define EPxCS_AR BITS(0, 3) /*!< endpoint address */ + +/* USBD_LPMCS */ +#define LPMCS_BLSTAT BITS(4, 7) /*!< bLinkState value */ +#define LPMCS_REMWK BIT(3) /*!< bRemoteWake value */ +#define LPMCS_LPMACK BIT(1) /*!< LPM token acknowledge enable */ +#define LPMCS_LPMEN BIT(0) /*!< LPM support enable */ + +/* constants definitions */ +/* endpoint control and status register mask (no toggle fields) */ +#define EPCS_MASK (EPxCS_RX_ST | EPxCS_SETUP | \ + EPxCS_CTL | EPxCS_KCTL | EPxCS_TX_ST | EPxCS_AR) + +/* EPxCS_CTL[1:0] endpoint type control */ +#define ENDP_TYPE(regval) (EPxCS_CTL & ((regval) << 9U)) + +#define EP_BULK ENDP_TYPE(0U) /* bulk transfers */ +#define EP_CONTROL ENDP_TYPE(1U) /* control transfers */ +#define EP_ISO ENDP_TYPE(2U) /* isochronous transfers */ +#define EP_INTERRUPT ENDP_TYPE(3U) /* interrupt transfers */ +#define EP_CTL_MASK (~EPxCS_CTL & EPCS_MASK) + +/* endpoint kind control mask */ +#define EPKCTL_MASK (~EPxCS_KCTL & EPCS_MASK) + +/* EPxCS_TX_STA[1:0] status for TX transfer */ +#define ENDP_TXSTAT(regval) (EPxCS_TX_STA & ((regval) << 4U)) + +#define EPTX_DISABLED ENDP_TXSTAT(0U) /* transmission state is disabled */ +#define EPTX_STALL ENDP_TXSTAT(1U) /* transmission state is STALL */ +#define EPTX_NAK ENDP_TXSTAT(2U) /* transmission state is NAK */ +#define EPTX_VALID ENDP_TXSTAT(3U) /* transmission state is enabled */ +#define EPTX_DTGMASK (EPxCS_TX_STA | EPCS_MASK) + +/* EPxCS_RX_STA[1:0] status for RX transfer */ +#define ENDP_RXSTAT(regval) (EPxCS_RX_STA & ((regval) << 12U)) + +#define EPRX_DISABLED ENDP_RXSTAT(0U) /* reception state is disabled */ +#define EPRX_STALL ENDP_RXSTAT(1U) /* reception state is STALL */ +#define EPRX_NAK ENDP_RXSTAT(2U) /* reception state is NAK */ +#define EPRX_VALID ENDP_RXSTAT(3U) /* reception state is enabled */ +#define EPRX_DTGMASK (EPxCS_RX_STA | EPCS_MASK) + +/* endpoint receive/transmission counter register bit definitions */ +#define EPRCNT_BLKSIZ BIT(15) /* reception data block size */ +#define EPRCNT_BLKNUM BITS(10, 14) /* reception data block number */ +#define EPRCNT_CNT BITS(0, 9) /* reception data count */ + +#define EPTCNT_CNT BITS(0, 9) /* transmisson data count */ + +/* interrupt flag clear bits */ +#define CLR(x) (USBD_INTF = ~INTF_##x) + +/* endpoint receive/transmission counter register bit offset */ +#define BLKSIZE_OFFSET (0x01U) +#define BLKNUM_OFFSET (0x05U) +#define RXCNT_OFFSET (0x0AU) + +#define TXCNT_OFFSET (0x0AU) + +#define BLKSIZE32_MASK (0x1fU) +#define BLKSIZE2_MASK (0x01U) + +#define BLKSIZE32_OFFSETMASK (0x05U) +#define BLKSIZE2_OFFSETMASK (0x01U) + +/* USBD operation macros */ + +/* TX or RX transfer status setting (bits EPTX_STA[1:0]) */ + +#define USBD_EP_TX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPTX_DTGMASK) ^ (stat); \ +} while(0) + +#define USBD_EP_RX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPRX_DTGMASK) ^ (stat); \ +} while(0) + +/* clear bit EPxCS_RX_ST/EPxCS_TX_ST in the endpoint control and status register */ + +#define USBD_EP_TX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_TX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +#define USBD_EP_RX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_RX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +/* toggle EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_TX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +#define USBD_RX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_RX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +/* clear EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_TX_DTG) != 0U) {\ + USBD_TX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_RX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_RX_DTG) != 0U) {\ + USBD_RX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_EP_DBL_BUF_SET(ep) (USBD_EPxCS(ep) = (USBD_EPxCS(ep) | EPxCS_KCTL) & EPCS_MASK) + +#endif /* __USBD_LLD_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c new file mode 100644 index 0000000000..0eafa0f641 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c @@ -0,0 +1,630 @@ +/*! + \file usbd_lld_core.c + \brief USB device low level driver core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_core.h" +#include "usbd_enum.h" + +#define USB_EPTYPE_MASK 0x03U + +#if defined (__CC_ARM) /* ARM Compiler */ +static usbd_ep_ram btable_ep[EP_COUNT]__attribute__((at(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)))); +#elif defined (__ICCARM__) /* IAR Compiler */ + __no_init usbd_ep_ram btable_ep[EP_COUNT] @(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#elif defined (__GNUC__) /* GNU GCC Compiler */ + usbd_ep_ram *btable_ep = (usbd_ep_ram *)(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#endif + +usb_core_drv usbd_core; + +static const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = EP_CONTROL, + [USB_EP_ATTR_BULK] = EP_BULK, + [USB_EP_ATTR_INT] = EP_INTERRUPT, + [USB_EP_ATTR_ISO] = EP_ISO +}; + +/* local function prototypes ('static') */ +static void usbd_dp_pullup (FlagStatus status); +static void usbd_core_reset (void); +static void usbd_core_stop (void); +static void usbd_address_set (usb_dev *udev); +static void usbd_ep_reset (usb_dev *udev); +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes); +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind); +static void usbd_resume (usb_dev *udev); +static void usbd_suspend (void); +static void usbd_leave_suspend (void); +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr); + +struct _usb_handler usbd_drv_handler = { + .dp_pullup = usbd_dp_pullup, + .init = usbd_core_reset, + .deinit = usbd_core_stop, + .suspend = usbd_suspend, + .suspend_leave = usbd_leave_suspend, + .resume = usbd_resume, + .set_addr = usbd_address_set, + .ep_reset = usbd_ep_reset, + .ep_disable = usbd_ep_disable, + .ep_setup = usbd_ep_setup, + .ep_rx_enable = usbd_ep_rx_enable, + .ep_write = usbd_ep_data_write, + .ep_read = usbd_ep_data_read, + .ep_stall_set = usbd_ep_stall_set, + .ep_stall_clear = usbd_ep_stall_clear, + .ep_status_get = usbd_ep_status +}; + +/*! + \brief free buffer used from application by toggling the SW_BUF byte + \param[in] ep_num: endpoint identifier (0..7) + \param[in] dir: endpoint direction which can be OUT(0) or IN(1) + \param[out] none + \retval None +*/ +void user_buffer_free (uint8_t ep_num, uint8_t dir) +{ + if ((uint8_t)DBUF_EP_OUT == dir) { + USBD_TX_DTG_TOGGLE(ep_num); + } else if ((uint8_t)DBUF_EP_IN == dir) { + USBD_RX_DTG_TOGGLE(ep_num); + } else { + /* no operation */ + } +} + +/*! + \brief set the status of pull-up pin + \param[in] status: SET or RESET + \param[out] none + \retval none +*/ +static void usbd_dp_pullup (FlagStatus status) +{ + if (SET == status) { + gpio_bit_set(USB_PULLUP, USB_PULLUP_PIN); + } else { + gpio_bit_reset(USB_PULLUP, USB_PULLUP_PIN); + } +} + +/*! + \brief device core register initialization + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_reset (void) +{ + /* reset the CLOSE bit */ + USBD_CTL = CTL_SETRST; + + /* may be need wait some time(tSTARTUP) ... */ + + /* clear SETRST bit in USBD_CTL register */ + USBD_CTL = 0U; + + /* clear all pending interrupts */ + USBD_INTF = 0U; + + /* set descriptors table offset in USB dedicated SRAM */ + USBD_BADDR = BTABLE_OFFSET & 0xFFF8U; + +#ifdef LPM_ENABLED + /* enable L1REQ interrupt */ + USBD_CTL = CTL_L1REQIE; + + USBD_LPMCS = LPMCS_LPMACK | LPMCS_LPMEN; +#endif /* LPM_ENABLED */ + + /* enable all interrupts mask bits */ + USBD_CTL |= CTL_STIE | CTL_WKUPIE | CTL_SPSIE | CTL_SOFIE | CTL_ESOFIE | CTL_RSTIE; +} + +/*! + \brief device core register configure when stop device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_stop (void) +{ + /* disable all interrupts and set USB reset */ + USBD_CTL = CTL_SETRST; + + /* clear all interrupt flags */ + USBD_INTF = 0U; + + /* close device */ + USBD_CTL = CTL_SETRST | CTL_CLOSE; +} + +/*! + \brief set device address + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_address_set (usb_dev *udev) +{ + USBD_DADDR = DADDR_USBEN | udev->dev_addr; +} + +/*! + \brief handle USB reset event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_ep_reset (usb_dev *udev) +{ + uint8_t i = 0U; + + usb_transc *transc = &udev->transc_in[0]; + + btable_ep[0].tx_addr = EP0_TX_ADDR; + btable_ep[0].tx_count = 0U; + + transc->max_len = USBD_EP0_MAX_SIZE; + + transc = &udev->transc_out[0]; + + btable_ep[0].rx_addr = EP0_RX_ADDR; + + transc->max_len = USBD_EP0_MAX_SIZE; + + if (transc->max_len > 62U) { + btable_ep[0].rx_count = ((uint16_t)((uint16_t)transc->max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[0].rx_count = ((transc->max_len + 1U) & ~1U) << 9U; + } + + /* reset non-control endpoints */ + for (i = 1U; i < EP_COUNT; i++) { + USBD_EPxCS(i) = (USBD_EPxCS(i) & EPCS_MASK) | i; + } + + /* clear endpoint 0 register */ + USBD_EPxCS(0U)= (uint16_t)(USBD_EPxCS(0U)); + + USBD_EPxCS(0U) = EP_CONTROL | EPRX_VALID | EPTX_NAK; + + /* set device address as default address 0 */ + USBD_DADDR = DADDR_USBEN; + + udev->cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: endpoint buffer address + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = EP_ID(ep_addr); + uint16_t max_len = ep_desc->wMaxPacketSize; + + usb_transc *transc = NULL; + + /* set the endpoint type */ + USBD_EPxCS(ep_num) = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK] | ep_num; + + if (EP_DIR(ep_addr)) { + transc = &udev->transc_in[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].tx_addr = buf_addr; + + /* configure the endpoint status as NAK status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } else { + /* error operation */ + } + } else { + transc = &udev->transc_out[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].rx_addr = buf_addr; + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + USBD_TX_DTG_TOGGLE(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + if (max_len > 62U) { + btable_ep[ep_num].tx_count = (((uint32_t)max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].tx_count = ((max_len + 1U) & ~1U) << 9U; + } + } else { + /* error operation */ + } + + if (max_len > 62U) { + btable_ep[ep_num].rx_count = (((uint32_t)max_len << 5U) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].rx_count = ((max_len + 1U) & ~1U) << 9U; + } + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + /* configure the endpoint status as NAK status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else { + /* error operation */ + } + } +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + USBD_TX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_DISABLED); + } else { + USBD_RX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } +} + +/*! + \brief enable endpoint to receive + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + /* enable endpoint to receive */ + USBD_EP_RX_STAT_SET(EP_ID(ep_addr), EPRX_VALID); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (0U == ep_num) { + USBD_EP_TX_STAT_SET(0U, EPTX_STALL); + USBD_EP_RX_STAT_SET(0U, EPRX_STALL); + } else { + if (EP_DIR(ep_addr)) { + udev->transc_in[ep_num].ep_stall = 1U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_STALL); + } else { + udev->transc_out[ep_num].ep_stall = 1U; + + USBD_EP_RX_STAT_SET(ep_num, EPRX_STALL); + } + } +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + /* clear endpoint data toggle bit */ + USBD_TX_DTG_CLEAR(ep_num); + + udev->transc_in[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + } else { + /* clear endpoint data toggle bit */ + USBD_RX_DTG_CLEAR(ep_num); + + udev->transc_out[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_VALID); + } +} + +/*! + \brief get the endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval endpoint status +*/ +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint32_t epcs = USBD_EPxCS(EP_ID(ep_addr)); + + if (EP_DIR(ep_addr)) { + return (uint8_t)(epcs & EPxCS_TX_STA); + } else { + return (uint8_t)(epcs & EPxCS_RX_STA); + } +} + +/*! + \brief write data from user FIFO to USB RAM + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] bytes: the bytes count of the write data + \param[out] none + \retval none +*/ +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes) +{ + if (0U != bytes) { + uint32_t n; + uint32_t *write_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *write_addr++ = *((uint16_t*)user_fifo); + user_fifo += 2U; + } + } + + btable_ep[ep_num].tx_count = bytes; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); +} + +/*! + \brief read data from USBRAM to user FIFO + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] buf_kind: endpoint buffer kind + \param[out] none + \retval none +*/ +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind) +{ + uint16_t n = 0U, bytes = 0U; + uint32_t *read_addr = NULL; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + if (USBD_EPxCS(ep_num) & EPxCS_TX_DTG) { + bytes = (uint16_t)(btable_ep[ep_num].tx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + } else { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } + } else { + return 0U; + } + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *((uint16_t*)user_fifo) = (uint16_t)*read_addr++; + user_fifo += 2U; + } + + return bytes; +} + +#ifdef USBD_LOWPWR_MODE_ENABLE + +/*! + \brief restore system clocks and power while exiting from suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void lowpower_mode_exit (void) +{ + /* restore system clock */ + +#ifdef LPM_ENABLED + /* enable IRC8M */ + rcu_osci_on(RCU_IRC8M); + + /* wait till IRC8M is ready */ + while (RESET == rcu_flag_get(RCU_FLAG_IRC8MSTB)) { + } +#else + /* enable HXTAL */ + rcu_osci_on(RCU_HXTAL); + + /* wait till HXTAL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_HXTALSTB)) { + } +#endif + + /* enable PLL */ + rcu_osci_on(RCU_PLL_CK); + + /* wait till PLL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_PLLSTB)) { + } + + /* select PLL as system clock source */ + rcu_system_clock_source_config(RCU_CKSYSSRC_PLL); + + /* wait till PLL is used as system clock source */ + while(0x08U != rcu_system_clock_source_get()) { + } + + /* low power sleep on exit disabled */ + system_lowpower_reset(SCB_LPM_DEEPSLEEP); +} + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + +/*! + \brief resume the USB device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_resume (usb_dev *udev) +{ +#ifdef LPM_ENABLED + if(1 == udev->lpm.L1_remote_wakeup){ + USBD_CTL |= CTL_L1RSREQ; + } +#endif /* LPM_ENABLED */ + + if(1U == usbd_core.dev->pm.remote_wakeup){ + /* make USB resume */ + USBD_CTL |= CTL_RSREQ; + } +} + +/*! + \brief set USB device to leave mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_leave_suspend (void) +{ + /* clear low_power mode bit in USBD_CTL */ + USBD_CTL &= ~CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* restore normal operations */ + lowpower_mode_exit(); + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + + /* clear SETSPS bit */ + USBD_CTL &= ~CTL_SETSPS; +} + +/*! + \brief set USB device to enter suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_suspend (void) +{ + /* set USB module to suspend and low-power mode */ + USBD_CTL |= CTL_SETSPS | CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* check wakeup flag is set */ + if (0U == (USBD_INTF & INTF_WKUPIF)) { + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } else { + /* clear wakeup interrupt flag */ + CLR(WKUPIF); + + /* clear set_suspend flag */ + USBD_CTL &= ~CTL_SETSPS; + } + +#endif /* USBD_LOWPWR_MODE_ENABLE */ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c new file mode 100644 index 0000000000..c00e72638a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c @@ -0,0 +1,276 @@ + /*! + \file usbd_lld_int.c + \brief USB device low level interrupt routines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_int.h" +#include "usbd_lld_core.h" + +/* local function prototypes ('static') */ +static void usbd_int_suspend (usb_dev *udev); + +/*! + \brief handle USB high priority successful transfer event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_int_hpst (usb_dev *udev) +{ + __IO uint16_t int_status = 0U; + + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + uint8_t transc_num = (uint8_t)TRANSC_UNKNOWN; + + if (int_status & INTF_DIR) { + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + uint16_t count = 0U; + + usb_transc *transc = &udev->transc_out[ep_num]; + + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_DBL); + + user_buffer_free(ep_num, (uint8_t)DBUF_EP_OUT); + + transc->xfer_buf += count; + transc->xfer_count += count; + transc->xfer_len -= count; + + if ((0U == transc->xfer_len) || (count < transc->max_len)) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + + transc_num = (uint8_t)TRANSC_OUT; + } + } + } else { + /* handle the in direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + transc_num = (uint8_t)TRANSC_IN; + } + } + + if ((uint8_t)TRANSC_UNKNOWN != transc_num) { + udev->ep_transc[ep_num][transc_num](udev, ep_num); + } + } +} + +/*! + \brief USB interrupt events service routine + \param[in] none + \param[out] none + \retval none +*/ +void usbd_isr (void) +{ + __IO uint16_t int_status = (uint16_t)USBD_INTF; + __IO uint16_t int_flag = (uint16_t)(USBD_INTF & (USBD_CTL & USBD_INTEN)); + + usb_dev *udev = usbd_core.dev; + + if (INTF_STIF & int_flag) { + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + if (int_status & INTF_DIR) { + /* handle the USB OUT direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + if (USBD_EPxCS(ep_num) & EPxCS_SETUP) { + + if (ep_num == 0U) { + udev->ep_transc[ep_num][TRANSC_SETUP](udev, ep_num); + } else { + return; + } + } else { + usb_transc *transc = &udev->transc_out[ep_num]; + + uint16_t count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_SNG); + + transc->xfer_buf += count; + transc->xfer_count += count; + + if ((transc->xfer_count >= transc->xfer_len) || (count < transc->max_len)) { + if (udev->ep_transc[ep_num][TRANSC_OUT]) { + udev->ep_transc[ep_num][TRANSC_OUT](udev, ep_num); + } + } else { + udev->drv_handler->ep_rx_enable(udev, ep_num); + } + } + } + } else { + /* handle the USB IN direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + usb_transc *transc = &udev->transc_in[ep_num]; + + if (transc->xfer_len == 0U) { + if (udev->ep_transc[ep_num][TRANSC_IN]) { + udev->ep_transc[ep_num][TRANSC_IN](udev, ep_num); + } + } else { + usbd_ep_send(udev, ep_num, transc->xfer_buf, transc->xfer_len); + } + } + } + } + } + + if (INTF_WKUPIF & int_flag) { + /* clear wakeup interrupt flag in INTF */ + CLR(WKUPIF); + + /* restore the old cur_status */ + udev->cur_status = udev->backup_status; + +#ifdef LPM_ENABLED + if ((0U == udev->pm.remote_wakeup_on) && (0U == udev->lpm.L1_resume)) { + resume_mcu(udev); + } else if (1U == udev->pm.remote_wakeup_on) { + /* no operation */ + } else { + udev->lpm.L1_resume = 0U; + } + + /* clear L1 remote wakeup flag */ + udev->lpm.L1_remote_wakeup = 0U; +#else + if (0U == udev->pm.remote_wakeup_on) { + resume_mcu(udev); + } +#endif /* LPM_ENABLED */ + } + + if (INTF_SPSIF & int_flag) { + if(!(USBD_CTL & CTL_RSREQ)) { + usbd_int_suspend (udev); + + /* clear of suspend interrupt flag bit must be done after setting of CTLR_SETSPS */ + CLR(SPSIF); + } + } + + if (INTF_SOFIF & int_flag) { + /* clear SOF interrupt flag in INTF */ + CLR(SOFIF); + + /* if necessary, user can add code here */ + if (NULL != usbd_int_fops) { + (void)usbd_int_fops->SOF(udev); + } + } + + if (INTF_ESOFIF & int_flag) { + /* clear ESOF interrupt flag in INTF */ + CLR(ESOFIF); + + /* control resume time by ESOFs */ + if (udev->pm.esof_count > 0U) { + if (0U == --udev->pm.esof_count) { + if (udev->pm.remote_wakeup_on) { + USBD_CTL &= ~CTL_RSREQ; + + udev->pm.remote_wakeup_on = 0U; + } else { + USBD_CTL |= CTL_RSREQ; + + udev->pm.esof_count = 3U; + udev->pm.remote_wakeup_on = 1U; + } + } + } + } + + if (INTF_RSTIF & int_flag) { + /* clear reset interrupt flag in INTF */ + CLR(RSTIF); + + udev->drv_handler->ep_reset(udev); + } + +#ifdef LPM_ENABLED + if (INTF_L1REQ & int_flag) { + /* clear L1 ST bit in LPM INTF */ + USBD_INTF = CLR(L1REQ); + + /* read BESL field from subendpoint0 register which corresponds to HIRD parameter in LPM spec */ + udev->lpm.besl = (USBD_LPMCS & LPMCS_BLSTAT) >> 4; + + /* read BREMOTEWAKE bit from subendpoint0 register which corresponding to bRemoteWake bit in LPM request */ + udev->lpm.L1_remote_wakeup = (USBD_LPMCS & LPMCS_REMWK) >> 3; + + /* process USB device core layer suspend routine */ + usbd_int_suspend(udev); + } +#endif /* LPM_ENABLED */ +} + +/*! + \brief handle USB suspend event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_int_suspend (usb_dev *udev) +{ + /* store the device current status */ + udev->backup_status = udev->cur_status; + + /* set device in suspended state */ + udev->cur_status = (uint8_t)USBD_SUSPENDED; + + /* usb enter in suspend mode and mcu system in low power mode */ + if (udev->pm.suspend_enabled) { + usbd_to_suspend(udev); + } else { + /* if not possible then resume after xx ms */ + udev->pm.esof_count = 3U; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..fabf9f3dc8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..46c8f8b2d9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..e392bf3054 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,811 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_set_intf (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .set_intf = audio_set_intf, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* volume Minimum Value */ +#define VOL_MAX 100U /* volume Maximum Value */ +#define VOL_RES 1U /* volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize TX endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle the AUDIO set interface requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_set_intf(usb_dev *udev, usb_req *req) +{ + udev->dev.class_core->alter_set = req->wValue; + + return USBD_OK; +} + + +/*! + \brief handles the control transfer OUT callback + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..fc3c3040e6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,228 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..df6d33e60e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..9a110a8333 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,524 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_proc = cdc_acm_req, + .ctlx_out = cdc_ctlx_out, + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command TX endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + transc = &udev->dev.transc_out[0]; + + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + transc = &udev->dev.transc_in[0]; + + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +static uint8_t cdc_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..20af740979 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..5393fca608 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..2767d02845 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,653 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); + +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static const usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..4323b5b7b1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..a20ba15c48 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..313517dd85 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..345637ee18 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,489 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* Initialize the data RX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..90353516c8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,390 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" + +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation function structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..1f091eacc2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,87 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..5e2adce144 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,563 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize TX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize RX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize IAP endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the IAP class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..f97dcac2b8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..7c47554914 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..7f038ec568 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..a992e0182e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..1123541b77 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..773644a01d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the RX FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the TX FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..36cc11bc95 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,319 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +__ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC TX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC RX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..e7084cdbac --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..3937fa6224 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,724 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..4b1308df7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..bb09bcef01 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,309 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..2325acfa6c --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions prototype + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..122f67c686 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..e38db7804f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..0911091009 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..e3166041f1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..cf50d93e4a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,265 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..10f2594a6d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,163 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the TX FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the RX FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a TX FIFO or all TX FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire RX FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..bbed1691bb --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,300 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< deinitialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device contrl in callback */ + uint8_t (*ctlx_out) (usb_dev *udev); /*!< device contrl out callback */ + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + usb_perp_dev dev; /*!< USB peripheral device */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..d8a6d7da0d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,193 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; + usb_core_regs regs; + usb_host_drv host; +} usb_core_driver; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..7af67edf3b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,69 @@ +/*! + \file drv_usb_hw.h + \brief USB hardware configuration header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +/* configure the CTC peripheral */ +#ifdef USE_IRC48M + void ctc_config(void); +#endif /* USE_IRC48M */ + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..76729b9641 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,662 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/** + * @brief USB IN endpoint 0 transmit FIFO length register bits definitions + */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..09cddd8d11 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..80ba44f3d6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*port_enabled) (usbh_host *uhost); + uint8_t (*port_disabled) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..1619583933 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,344 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initialize the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the TX FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a TX FIFO or all TX FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for TX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for RX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (fifo == 0U) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..6589ca0fa7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,612 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 1 to 3's TX FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all TX FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire RX FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the TX FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure USB transaction to start OUT transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..feaa32e9d7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,452 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected USB host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic TX FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic TX FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all TX FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == udev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the TX fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..570ff19744 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,497 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); + +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + udev->dev.cur_status = USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: +#ifdef GD32F10X_CL + #ifdef CDC_DATA_IN_EP + udev->regs.dr->DAEPINTEN |= (uint32_t)(1U << (EP_ID(CDC_DATA_IN_EP) + 16U)); + #endif /* CDC_DATA_IN_EP */ +#endif /* GD32F10X_CL */ + + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the TX FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..2a1f442309 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(udev->host.data); + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(udev->host.data); + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == udev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + udev->host.backup_xfercount[pp_num] = udev->host.pipe[pp_num].xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..8f9a6ca9fc --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + void (*machine)(usb_core_driver *udev, usbh_host *uhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..5825219e33 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void USR_KEYBRD_Init (void); +/* process keyboard data */ +void USR_KEYBRD_ProcessData (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..f835ea9391 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void USR_MOUSE_Init (void); +/* process mouse data */ +void USR_MOUSE_ProcessData (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..dcefd810e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,62 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..6ad3e93557 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..35e97af107 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,676 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" + +#include +#include + +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *uhost); +static usbh_status usbh_hid_itf_init (usbh_host *uhost); +static usbh_status usbh_hid_class_req (usbh_host *uhost); +static usbh_status usbh_hid_handle (usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief deinitialize the host pipes used for the HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CHECK_CLASS == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check fifo available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(uhost->data, uhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to USB host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to USB host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..1905f0e040 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user initialization*/ + USR_KEYBRD_Init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(udev, uhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(udev, uhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + USR_KEYBRD_ProcessData(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..14ebeaa747 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + USR_MOUSE_Init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if(usbh_hid_mouse_decode(udev, uhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(udev, uhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + USR_MOUSE_ProcessData(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..420b703ed8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: OK) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..9184a816ae --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *uhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction); +/* reset MSC bot request structure */ +usbh_status usbh_msc_bot_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..f6e41ff1d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for MSC process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..c38d0d74a4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..d8031fab08 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (uhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(uhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to USB host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeture command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset MSC bot transfer + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to USB host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..1285b97e2b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,561 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0, sizeof(usbh_msc_handler)); + + uhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(uhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(uhost->data, msc_handler.ep_in); + + usbh_msc_bot_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief deinitialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clearfeature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for receive error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if (((uhost->control.timer > msc->timer) && ((uhost->control.timer - msc->timer) < 10000U)) \ + || ((uhost->control.timer < msc->timer) && ((uhost->control.timer + 0x3FFFU - msc->timer) < 10000U))){ + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch MSC req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle MSC read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer > timeout) && ((uhost->control.timer - timeout) > (1000U * length))) \ + || ((uhost->control.timer < timeout) && ((uhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == udev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle MSC write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer > timeout) && ((uhost->control.timer - timeout) > (1000U * length))) \ + || ((uhost->control.timer < timeout) && ((uhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == udev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..d54c5f7cc1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..8120a9bdde --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implemention + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..689fe0d29f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,274 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* deinitialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..81ed701bc3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..f18d6a5a44 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..433d5087ee --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..aee70bba18 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,650 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *uhost); +static uint8_t usbh_connect (usbh_host *uhost); +static uint8_t usbh_disconnect (usbh_host *uhost); +static uint8_t usbh_port_enabled (usbh_host *uhost); +static uint8_t usbh_port_disabled (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#ifdef USB_FS_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *udev); +static void usb_hwp_resume(usb_core_driver *udev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)uhost; + uhost->data = (void *)&usbh_core; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to USB host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief deinitialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, uhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + uhost->cur_state = HOST_DEV_ATTACHED; + + uhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#ifdef USB_FS_LOW_PWR_ENABLE + uhost->cur_state = HOST_SUSPENDED; +#else + uhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CHECK_CLASS; + } + } else { + uhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (0U == uhost->class_num) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_FS_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + uhost->suspend_flag = 1; + usb_hwp_suspend(uhost->data); + uhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + + uhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit(uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(&usbh_core); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *uhost) +{ + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[64]; + + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 max packet size */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + + +#ifdef USB_FS_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif /* USB_LOW_PWR_ENABLE */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..14a42c3052 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumberation driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to USB host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to USB host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to USB host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to USB host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to USB device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to USB configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to USB interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to USB endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..2310216fe1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to USB core instance + \param[in] dev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(dev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HC_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..c5917b7476 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,371 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* Toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(uhost->data)- uhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..c7f77e07dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..bd00508b3e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..32a259101b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..6a8aac60cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..4c6b971fbb --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..4b366f2d6d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript new file mode 100644 index 0000000000..f5004445c0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript @@ -0,0 +1,60 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/GD/GD32F10x/Source/system_gd32f10x.c +GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c +GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c +GD32F10x_standard_peripheral/Source/gd32f10x_exti.c +GD32F10x_standard_peripheral/Source/gd32f10x_misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_enet.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_dac.c'] + +if GetDepend(['RT_USING_HWTIMER']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_timer.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c'] + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c'] + +path = [ + cwd + '/CMSIS/GD/GD32F10x/Include', + cwd + '/CMSIS', + cwd + '/GD32F10x_standard_peripheral/Include',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h new file mode 100644 index 0000000000..4929c455df --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h @@ -0,0 +1,272 @@ +/*! + \file gd32f20x.h + \brief general definitions for GD32F20x + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_H +#define GD32F20X_H + +#ifdef cplusplus + extern "C" { +#endif + +/* define GD32F20x */ +#if !defined (GD32F20X_CL) + #error "Please select first the target gd32f20x device used in your application (in gd32f20x.h file)" +#endif /* GD32F20X */ + +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32F20X_CL +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#endif /* HXTAL_VALUE */ +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined (HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined (IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined (IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined (IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined (LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* GD32F20x firmware library version number V2.0 */ +#define __GD32F20x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __GD32F20x_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __GD32F20x_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __GD32F20x_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F20x_STDPERIPH_VERSION ((__GD32F20x_STDPERIPH_VERSION_MAIN << 24)\ + |(__GD32F20x_STDPERIPH_VERSION_SUB1 << 16)\ + |(__GD32F20x_STDPERIPH_VERSION_SUB2 << 8)\ + |(__GD32F20x_STDPERIPH_VERSION_RC)) + +/* configuration of the Cortex-M3 processor and core peripherals */ +#define __MPU_PRESENT 0 /*!< GD32 devices does not provide an MPU */ +#define __NVIC_PRIO_BITS 4 /*!< GD32F20X uses 4 bits for the Priority levels */ +#define __VENDOR_SYSTICKCONFIG 0 /*!< set to 1 if different systick config is used */ + +/* define interrupt number */ +typedef enum IRQn +{ + /* Cortex-M3 processor exceptions numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 system tick interrupt */ + /* interruput numbers */ + WWDGT_IRQn = 0, /*!< WWDGT interrupt */ + LVD_IRQn = 1, /*!< LVD from EXTI line interrupt */ + TAMPER_IRQn = 2, /*!< tamper interrupt */ + RTC_IRQn = 3, /*!< RTC global interrupt */ + FMC_IRQn = 4, /*!< FMC global interrupt */ + RCU_IRQn = 5, /*!< RCU global interrupt */ + EXTI0_IRQn = 6, /*!< EXTI line0 interrupt */ + EXTI1_IRQn = 7, /*!< EXTI line1 interrupt */ + EXTI2_IRQn = 8, /*!< EXTI line2 interrupt */ + EXTI3_IRQn = 9, /*!< EXTI line3 interrupt */ + EXTI4_IRQn = 10, /*!< EXTI line4 interrupt */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel 0 global interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel 1 global interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel 2 global interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel 3 global interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel 4 global interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel 5 global interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel 6 global interrupt */ + ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 global interrupts */ + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupt */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupt */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break interrupt and TIMER8 global interrupt */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update Interrupt and TIMER9 global interrupt */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation interrupt and TIMER10 global interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 global interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 global interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 global interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 global interrupt */ + SPI1_IRQn = 36, /*!< SPI1 global interrupt */ + USART0_IRQn = 37, /*!< USART0 global interrupt */ + USART1_IRQn = 38, /*!< USART1 global interrupt */ + USART2_IRQn = 39, /*!< USART2 global interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm from EXTI line interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeUp from EXTI line interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break interrupt and TIMER11 global interrupt */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update interrupt and TIMER12 global interrupt */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation interrupt and TIMER13 global interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 Channel Capture Compare Interrupt */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 Channel 0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 Channel 1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 Channel 2 global interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 Channel 3 global interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 Channel 4 global interrupt */ + ENET_IRQn = 61, /*!< ENET global interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET wakeup through EXTI line interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ + DMA1_Channel5_IRQn = 69, /*!< DMA1 Channel 5 global interrupt */ + DMA1_Channel6_IRQn = 70, /*!< DMA1 Channel 6 global interrupt */ + USART5_IRQn = 71, /*!< USART5 global interrupt */ + I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ + I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ + DCI_IRQn = 78, /*!< DCI global interrupt */ + CAU_IRQn = 79, /*!< CAU global interrupt */ + HAU_TRNG_IRQn = 80, /*!< HAU or TRNG global interrupt */ + UART6_IRQn = 82, /*!< UART6 global interrupt */ + UART7_IRQn = 83, /*!< UART7 global interrupt */ + TLI_IRQn = 88, /*!< TLI global interrupt */ + TLI_ER_IRQn = 89 /*!< TLI global error interrupt */ +} IRQn_Type; + +/* includes */ +#include "core_cm3.h" +#include "system_gd32f20x.h" +#include + +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +typedef enum {FALSE = 0, TRUE = !FALSE} bool; +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define SRAM_BB_BASE ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB2_BUS_BASE ((uint32_t)0x50000000U) /*!< ahb2 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ +#define TLI_BASE (APB2_BUS_BASE + 0x00006800U) /*!< TLI base address */ + +/* advanced high performance bus 1 memory map */ +#define SDIO_BASE (AHB1_BUS_BASE + 0x00000000U) /*!< SDIO base address */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define ENET_BASE (AHB1_BUS_BASE + 0x00010000U) /*!< ENET base address */ + +/* advanced high performance bus 2 memory map */ +#define USBFS_BASE (AHB2_BUS_BASE + 0x00000000U) /*!< USBFS base address */ +#define DCI_BASE (AHB2_BUS_BASE + 0x00050000U) /*!< DCI base address */ +#define CAU_BASE (AHB2_BUS_BASE + 0x00060000U) /*!< CAU base address */ +#define HAU_BASE (AHB2_BUS_BASE + 0x00060400U) /*!< HAU base address */ +#define TRNG_BASE (AHB2_BUS_BASE + 0x00060800U) /*!< TRNG base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32f20x_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef cplusplus +} +#endif +#endif diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h new file mode 100644 index 0000000000..6550880290 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h @@ -0,0 +1,58 @@ +/*! + \file system_gd32f20x.h + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File for + GD32F20x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32F20X_H +#define SYSTEM_GD32F20X_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit (void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32F20X_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s new file mode 100644 index 0000000000..5b3128e8e2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s @@ -0,0 +1,436 @@ +;/*! +; \file startup_gd32f20x_cl.s +; \brief start up file + +; \version 2015-07-15, V1.0.0, firmware for GD32F20x +; \version 2017-06-05, V2.0.0, firmware for GD32F20x +; \version 2018-10-31, V2.1.0, firmware for GD32F20x +; \version 2020-09-30, V2.2.0, firmware for GD32F20x +;*/ + +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. + +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; 58:USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + DCD 0 ; 84:Reserved + DCD DMA1_Channel5_IRQHandler ; 85:DMA1 Channel5 + DCD DMA1_Channel6_IRQHandler ; 86:DMA1 Channel6 + DCD USART5_IRQHandler ; 87:USART5 + DCD I2C2_EV_IRQHandler ; 88:I2C2 Event + DCD I2C2_ER_IRQHandler ; 89:I2C2 Error + DCD 0 ; 90:Reserved + DCD 0 ; 91:Reserved + DCD 0 ; 92:Reserved + DCD 0 ; 93:Reserved + DCD DCI_IRQHandler ; 94:DCI + DCD CAU_IRQHandler ; 95:CAU + DCD HAU_TRNG_IRQHandler ; 96:HAU and TRNG + DCD 0 ; 97:Reserved + DCD UART6_IRQHandler ; 98:UART6 + DCD UART7_IRQHandler ; 99:UART7 + DCD 0 ; 100:Reserved + DCD 0 ; 101:Reserved + DCD 0 ; 102:Reserved + DCD 0 ; 103:Reserved + DCD TLI_IRQHandler ; 104:TLI + DCD TLI_ER_IRQHandler ; 105:TLI error +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT CAN0_TX_IRQHandler [WEAK] + EXPORT CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBFS_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT ENET_IRQHandler [WEAK] + EXPORT ENET_WKUP_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_EWMC_IRQHandler [WEAK] + EXPORT USBFS_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT USART5_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT DCI_IRQHandler [WEAK] + EXPORT CAU_IRQHandler [WEAK] + EXPORT HAU_TRNG_IRQHandler [WEAK] + EXPORT UART6_IRQHandler [WEAK] + EXPORT UART7_IRQHandler [WEAK] + EXPORT TLI_IRQHandler [WEAK] + EXPORT TLI_ER_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +CAN0_TX_IRQHandler +CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBFS_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +ENET_IRQHandler +ENET_WKUP_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_EWMC_IRQHandler +USBFS_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +USART5_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +DCI_IRQHandler +CAU_IRQHandler +HAU_TRNG_IRQHandler +UART6_IRQHandler +UART7_IRQHandler +TLI_IRQHandler +TLI_ER_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s new file mode 100644 index 0000000000..c03d09f026 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s @@ -0,0 +1,307 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word CAN0_TX_IRQHandler // 35:CAN0 TX + .word CAN0_RX0_IRQHandler // 36:CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI Line 5 to EXTI Line 9 + .word TIMER0_BRK_TIMER8_IRQHandler // 40:TIMER0 Break and TIMER8 global + .word TIMER0_UP_TIMER9_IRQHandler // 41:TIMER0 Update and TIMER9 global + .word TIMER0_TRG_CMT_TIMER10_IRQHandler // 42:TIMER0 Trigger and Commutation and TIMER10 global + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBFS_WKUP_IRQHandler // 58:USBFS WakeUp from suspend through EXTI Line + .word TIMER7_BRK_TIMER11_IRQHandler // 59:TIMER7 Break Interrupt and TIMER11 global + .word TIMER7_UP_TIMER12_IRQHandler // 60:TIMER7 Update Interrupt and TIMER12 global + .word TIMER7_TRG_CMT_TIMER13_IRQHandler // 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_IRQHandler // 75:DMA1 Channel3 + .word DMA1_Channel4_IRQHandler // 76:DMA1 Channel4 + .word ENET_IRQHandler // 77:Ethernet + .word ENET_WKUP_IRQHandler // 78:Ethernet Wakeup through EXTI Line + .word CAN1_TX_IRQHandler // 79:CAN1 TX + .word CAN1_RX0_IRQHandler // 80:CAN1 RX0 + .word CAN1_RX1_IRQHandler // 81:CAN1 RX1 + .word CAN1_EWMC_IRQHandler // 82:CAN1 EWMC + .word USBFS_IRQHandler // 83:USBFS + .word 0 // 84:Reserved + .word DMA1_Channel5_IRQHandler // 85:DMA1 Channel5 + .word DMA1_Channel6_IRQHandler // 86:DMA1 Channel6 + .word USART5_IRQHandler // 87:USART5 + .word I2C2_EV_IRQHandler // 88:I2C2 Event + .word I2C2_ER_IRQHandler // 89:I2C2 Error + .word 0 // 90:Reserved + .word 0 // 91:Reserved + .word 0 // 92:Reserved + .word 0 // 93:Reserved + .word DCI_IRQHandler // 94:DCI + .word CAU_IRQHandler // 95:CAU + .word HAU_TRNG_IRQHandler // 96:HAU and TRNG + .word 0 // 97:Reserved + .word UART6_IRQHandler // 98:UART6 + .word UART7_IRQHandler // 99:UART7 + .word 0 // 100:Reserved + .word 0 // 101:Reserved + .word 0 // 102:Reserved + .word 0 // 103:Reserved + .word TLI_IRQHandler // 104:TLI + .word TLI_ER_IRQHandler // 105:TLI error + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ CAN0_TX_IRQHandler + IRQ CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_TIMER8_IRQHandler + IRQ TIMER0_UP_TIMER9_IRQHandler + IRQ TIMER0_TRG_CMT_TIMER10_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBFS_WKUP_IRQHandler + IRQ TIMER7_BRK_TIMER11_IRQHandler + IRQ TIMER7_UP_TIMER12_IRQHandler + IRQ TIMER7_TRG_CMT_TIMER13_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_IRQHandler + IRQ DMA1_Channel4_IRQHandler + IRQ ENET_IRQHandler + IRQ ENET_WKUP_IRQHandler + IRQ CAN1_TX_IRQHandler + IRQ CAN1_RX0_IRQHandler + IRQ CAN1_RX1_IRQHandler + IRQ CAN1_EWMC_IRQHandler + IRQ USBFS_IRQHandler + IRQ DMA1_Channel5_IRQHandler + IRQ DMA1_Channel6_IRQHandler + IRQ USART5_IRQHandler + IRQ I2C2_EV_IRQHandler + IRQ I2C2_ER_IRQHandler + IRQ DCI_IRQHandler + IRQ CAU_IRQHandler + IRQ HAU_TRNG_IRQHandler + IRQ UART6_IRQHandler + IRQ UART7_IRQHandler + IRQ TLI_IRQHandler + IRQ TLI_ER_IRQHandler diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s new file mode 100644 index 0000000000..9759157a4f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s @@ -0,0 +1,621 @@ +;/*! +; \file startup_gd32f20x_cl.s +; \brief start up file + +; \version 2015-07-15, V1.0.0, firmware for GD32F20x +; \version 2017-06-05, V2.0.0, firmware for GD32F20x +; \version 2018-10-31, V2.1.0, firmware for GD32F20x +; \version 2020-09-30, V2.2.0, firmware for GD32F20x +;*/ + +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. + +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; Vector Number 35,CAN0 TX + DCD CAN0_RX0_IRQHandler ; Vector Number 36,CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; Vector Number 40,TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; Vector Number 41,TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; Vector Number 58,USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt and TIMER13 + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; Vector Number 63,ADC2 + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD SDIO_IRQHandler ; Vector Number 65,SDIO + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; Vector Number 75,DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; Vector Number 76,DMA1 Channel4 + DCD ENET_IRQHandler ; Vector Number 77,Ethernet + DCD ENET_WKUP_IRQHandler ; Vector Number 78,Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; Vector Number 79,CAN1 TX + DCD CAN1_RX0_IRQHandler ; Vector Number 80,CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; Vector Number 81,CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; Vector Number 82,CAN1 EWMC + DCD USBFS_IRQHandler ; Vector Number 83,USBFS + DCD 0 ; Vector Number 84,Reserved + DCD DMA1_Channel5_IRQHandler ; Vector Number 85,DMA1 Channel5 + DCD DMA1_Channel6_IRQHandler ; Vector Number 86,DMA1 Channel6 + DCD USART5_IRQHandler ; Vector Number 87,USART5 + DCD I2C2_EV_IRQHandler ; Vector Number 88,I2C2 Event + DCD I2C2_ER_IRQHandler ; Vector Number 89,I2C2 Error + DCD 0 ; Vector Number 90,Reserved + DCD 0 ; Vector Number 91,Reserved + DCD 0 ; Vector Number 92,Reserved + DCD 0 ; Vector Number 93,Reserved + DCD DCI_IRQHandler ; Vector Number 94,DCI + DCD CAU_IRQHandler ; Vector Number 95,CAU + DCD HAU_TRNG_IRQHandler ; Vector Number 96,HAU and TRNG + DCD 0 ; Vector Number 97,Reserved + DCD UART6_IRQHandler ; Vector Number 98,UART6 + DCD UART7_IRQHandler ; Vector Number 99,UART7 + DCD 0 ; Vector Number 100,Reserved + DCD 0 ; Vector Number 101,Reserved + DCD 0 ; Vector Number 102,Reserved + DCD 0 ; Vector Number 103,Reserved + DCD TLI_IRQHandler ; Vector Number 104,TLI + DCD TLI_ER_IRQHandler ; Vector Number 105,TLI error + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_TX_IRQHandler + B CAN0_TX_IRQHandler + + PUBWEAK CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX0_IRQHandler + B CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBFS_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_WKUP_IRQHandler + B USBFS_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK ENET_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_IRQHandler + B ENET_IRQHandler + + PUBWEAK ENET_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_WKUP_IRQHandler + B ENET_WKUP_IRQHandler + + PUBWEAK CAN1_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX0_IRQHandler + B CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_EWMC_IRQHandler + B CAN1_EWMC_IRQHandler + + PUBWEAK USBFS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_IRQHandler + B USBFS_IRQHandler + + PUBWEAK DMA1_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel5_IRQHandler + B DMA1_Channel5_IRQHandler + + PUBWEAK DMA1_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel6_IRQHandler + B DMA1_Channel6_IRQHandler + + PUBWEAK USART5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART5_IRQHandler + B USART5_IRQHandler + + PUBWEAK I2C2_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_EV_IRQHandler + B I2C2_EV_IRQHandler + + PUBWEAK I2C2_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_ER_IRQHandler + B I2C2_ER_IRQHandler + + PUBWEAK DCI_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DCI_IRQHandler + B DCI_IRQHandler + + PUBWEAK CAU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAU_IRQHandler + B CAU_IRQHandler + + PUBWEAK HAU_TRNG_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +HAU_TRNG_IRQHandler + B HAU_TRNG_IRQHandler + + PUBWEAK UART6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART6_IRQHandler + B UART6_IRQHandler + + PUBWEAK UART7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART7_IRQHandler + B UART7_IRQHandler + + PUBWEAK TLI_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TLI_IRQHandler + B TLI_IRQHandler + + PUBWEAK TLI_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TLI_ER_IRQHandler + B TLI_ER_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c new file mode 100644 index 0000000000..a3f76add9c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c @@ -0,0 +1,1113 @@ +/*! + \file system_gd32f20x.c + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File for + GD32F20x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#include "gd32f20x.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) +//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) + +/* use HXTAL */ +//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) +//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000) +//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) +//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) +#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) + + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U + +/* set the system clock frequency and declare the system clock configuration function */ +#ifdef __SYSTEM_CLOCK_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M; +static void system_clock_8m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M; +static void system_clock_120m_irc8m(void); + +#elif defined (__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL; +static void system_clock_24m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL; +static void system_clock_36m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL; +static void system_clock_56m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; +static void system_clock_96m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL; +static void system_clock_120m_hxtal(void); +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit (void) +{ + /* reset the RCC clock configuration to the default reset state */ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN ); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + + /* reset PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); + + /* reset CFG1 register */ + RCU_CFG1 = 0x00000000U; + + /* reset INT register */ + RCU_INT = 0x00FF0000U; + + /* reset CFG2 register */ + RCU_CFG2 = 0x00000000U; + + /* reset PLLTCTL register */ + RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); + + /* reset PLLTINT register */ + RCU_PLLTINT = 0x00400000U; + + /* Reset PLLTCFG register */ + RCU_PLLTCFG = 0x20003010U; + + /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); +} +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#ifdef __SYSTEM_CLOCK_IRC8M + system_clock_8m_irc8m(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) + system_clock_120m_irc8m(); + +#elif defined (__SYSTEM_CLOCK_HXTAL) + system_clock_hxtal(); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) + system_clock_24m_hxtal(); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) + system_clock_36m_hxtal(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) + system_clock_56m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) + system_clock_96m_hxtal(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) + system_clock_120m_hxtal(); +#endif /* __SYSTEM_CLOCK_IRC8M */ +} + +#ifdef __SYSTEM_CLOCK_IRC8M +/*! + \brief configure the system clock to 8M by IRC8M + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_8m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select IRC8M as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; + + /* wait until IRC8M is selected as system clock */ + while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL12); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL18); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL27); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +/*! + \brief configure the system clock to 120M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL30); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_HXTAL) +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +/*! + \brief configure the system clock to 24M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_24m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + + +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +/*! + \brief configure the system clock to 36M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_36m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + + +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 6 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +/*! + \brief configure the system clock to 56M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_56m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 7 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL7); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +/*! + \brief configure the system clock to 96M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_96m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 12 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +/*! + \brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 10 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL10); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate (void) +{ + uint32_t sws; + uint32_t pllsel, predv0sel, pllmf,ck_src; + uint32_t predv0, predv1, pll1mf; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if (RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src/predv1)*pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(13U == pllmf){ + /* PLL source clock multiply by 6.5 */ + SystemCoreClock = ck_src*6U + ck_src/2U; + }else{ + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + SystemCoreClock = ck_src*pllmf; + } + + break; + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } + +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h new file mode 100644 index 0000000000..74c49c67de --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h @@ -0,0 +1,734 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return(result); +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h new file mode 100644 index 0000000000..1b661b4421 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h @@ -0,0 +1,1638 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) /* Cosmic */ + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI__VFP_SUPPORT____ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200 + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h new file mode 100644 index 0000000000..3c932e0d6e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h @@ -0,0 +1,616 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h new file mode 100644 index 0000000000..597e64df04 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h @@ -0,0 +1,618 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + uint32_t result; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + + __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); + return(op1); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint8_t result; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint16_t result; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint8_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h new file mode 100644 index 0000000000..78ebb5e49c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h @@ -0,0 +1,411 @@ +/*! + \file gd32f20x_adc.h + \brief definitions for the ADC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_ADC_H +#define GD32F20X_ADC_H + +#include "gd32f20x.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) +#define ADC2 (ADC_BASE + 0x1800U) + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ +#define ADC_OVSAMPCTL(adcx) REG32((adcx) + 0x80U) /*!< ADC oversampling control register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0,4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13,15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16,19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17,19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger enable for regular channel */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0,1 */ +#define ADC_SAMPTX_SPTN BITS(0,2) /*!< channel n sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0,11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0,11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0,11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx x=0..2 */ +#define ADC_RSQX_RSQN BITS(0,4) /*!< x conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20,23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0,4) /*!< n conversion in regular sequence */ +#define ADC_ISQ_IL BITS(20,21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0,15) /*!< inserted channel x conversion data */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0,15) /*!< regular channel data */ +#define ADC_RDATA_ADC1RDTR BITS(16,31) /*!< ADC1 regular channel data */ + +/* ADC_OVSAMPCTL */ +#define ADC_OVSAMPCTL_OVSEN BIT(0) /*!< oversampling enable */ +#define ADC_OVSAMPCTL_OVSR BITS(2,4) /*!< oversampling ratio */ +#define ADC_OVSAMPCTL_OVSS BITS(5,8) /*!< oversampling shift */ +#define ADC_OVSAMPCTL_TOVS BIT(9) /*!< triggered oversampling */ +#define ADC_OVSAMPCTL_DRES BITS(12,13) /*!< oversampling shift */ + +/* constants definitions */ +/* adc_stat register value */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion flag */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted channel group conversion flag */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* scan mode */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ + +/* inserted channel group convert automatically */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ + +/* ADC sync mode */ +#define CTL0_SYNCM(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* adc_ctl1 register value */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* continuous mode */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +/* for ADC0 and ADC1 regular channel */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< TIMER0 CH0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< TIMER0 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< TIMER1 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< TIMER2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< TIMER3 CH3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(6) /*!< TIMER7 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_2_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ +/* for ADC2 regular channel */ +#define ADC2_EXTTRIG_REGULAR_T2_CH0 CTL1_ETSRC(0) /*!< TIMER2 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T1_CH2 CTL1_ETSRC(1) /*!< TIMER1 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_CH0 CTL1_ETSRC(3) /*!< TIMER7 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(4) /*!< TIMER7 TRGO event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< TIMER4 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< TIMER4 CH2 event select */ + +/* external trigger mode for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +/* for ADC0 and ADC1 inserted channel */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< TIMER1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< TIMER1 CH0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< TIMER2 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< TIMER3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(6) /*!< TIMER7 CH3 event select */ +#define ADC0_1_2_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ +/* for ADC2 inserted channel */ +#define ADC2_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T3_CH2 CTL1_ETSIC(2) /*!< TIMER3 CH2 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH1 CTL1_ETSIC(3) /*!< TIMER7 CH1 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(4) /*!< TIMER7 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T4_TRGO CTL1_ETSIC(5) /*!< TIMER4 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T4_CH3 CTL1_ETSIC(6) /*!< TIMER4 CH3 event select */ + +/* adc_samptx register value */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* adc_ovsampctl register value */ +#define OVSAMPCTL_DRES(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_OVSAMPCTL_DRES bit field */ +#define ADC_RESOLUTION_12B OVSAMPCTL_DRES(0) /*!< 12-bit ADC resolution */ +#define ADC_RESOLUTION_10B OVSAMPCTL_DRES(1) /*!< 10-bit ADC resolution */ +#define ADC_RESOLUTION_8B OVSAMPCTL_DRES(2) /*!< 8-bit ADC resolution */ +#define ADC_RESOLUTION_6B OVSAMPCTL_DRES(3) /*!< 6-bit ADC resolution */ + +#define OVSAMPCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) /*!< write value to ADC_OVSAMPCTL_OVSS bit field */ +#define ADC_OVERSAMPLING_SHIFT_NONE OVSAMPCTL_OVSS(0) /*!< no oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_1B OVSAMPCTL_OVSS(1) /*!< 1-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_2B OVSAMPCTL_OVSS(2) /*!< 2-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_3B OVSAMPCTL_OVSS(3) /*!< 3-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_4B OVSAMPCTL_OVSS(4) /*!< 4-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_5B OVSAMPCTL_OVSS(5) /*!< 5-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_6B OVSAMPCTL_OVSS(6) /*!< 6-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_7B OVSAMPCTL_OVSS(7) /*!< 7-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_8B OVSAMPCTL_OVSS(8) /*!< 8-bit oversampling shift */ + +#define OVSAMPCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ADC_OVSAMPCTL_OVSR bit field */ +#define ADC_OVERSAMPLING_RATIO_MUL2 OVSAMPCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ +#define ADC_OVERSAMPLING_RATIO_MUL4 OVSAMPCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ +#define ADC_OVERSAMPLING_RATIO_MUL8 OVSAMPCTL_OVSR(2) /*!< oversampling ratio multiple 8 */ +#define ADC_OVERSAMPLING_RATIO_MUL16 OVSAMPCTL_OVSR(3) /*!< oversampling ratio multiple 16 */ +#define ADC_OVERSAMPLING_RATIO_MUL32 OVSAMPCTL_OVSR(4) /*!< oversampling ratio multiple 32 */ +#define ADC_OVERSAMPLING_RATIO_MUL64 OVSAMPCTL_OVSR(5) /*!< oversampling ratio multiple 64 */ +#define ADC_OVERSAMPLING_RATIO_MUL128 OVSAMPCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ +#define ADC_OVERSAMPLING_RATIO_MUL256 OVSAMPCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ + +#define ADC_OVERSAMPLING_ALL_CONVERT 0U /*!< all oversampled conversions for a channel are done consecutively after a trigger */ +#define ADC_OVERSAMPLING_ONE_CONVERT 1U /*!< each oversampled conversion for a channel needs a trigger */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< ADC regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< ADC inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* function declarations */ +/* initialization configure */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* configure the ADC sync mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus new_value); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* function configuration */ +/* DMA configure */ +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); + +/* regular group and inserted group configure */ +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length); + +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset); + +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* configure ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group); + +/* get channel data */ +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* watchdog configure */ +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold); + +/* interrupt & flag functions */ +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); +/* get the ADC interrupt flag */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); +/* clear the ADC interrupt flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); + +/* configure ADC resolution */ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution); +/* configure ADC oversample mode */ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio); +/* enable ADC oversample mode */ +void adc_oversample_mode_enable(uint32_t adc_periph); +/* disable ADC oversample mode */ +void adc_oversample_mode_disable(uint32_t adc_periph); + +#endif /* GD32F20X_ADC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h new file mode 100644 index 0000000000..732c776880 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h @@ -0,0 +1,273 @@ +/*! + \file gd32f20x_bkp.h + \brief definitions for the BKP + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_BKP_H +#define GD32F20X_BKP_H + +#include "gd32f20x.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL0 REG16((BKP) + 0x30U) /*!< tamper pin control register 0 */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ +#define BKP_TPCTL1 REG16((BKP) + 0x38U) /*!< tamper pin control register 1 */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0,15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0,6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ +#define BKP_OCTL_CCOSEL BIT(14) /*!< RTC clock output selection */ +#define BKP_OCTL_CALDIR BIT(15) /*!< RTC clock calibration direction */ + +/* BKP_TPCTL0 */ +#define BKP_TPCTL0_TPEN0 BIT(0) /*!< tamper0 detection enable */ +#define BKP_TPCTL0_TPAL0 BIT(1) /*!< tamper0 pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER0 BIT(0) /*!< tamper0 event reset */ +#define BKP_TPCS_TIR0 BIT(1) /*!< tamper0 interrupt reset */ +#define BKP_TPCS_TPIE0 BIT(2) /*!< tamper0 interrupt enable */ +#define BKP_TPCS_TER1 BIT(5) /*!< tamper1 event reset */ +#define BKP_TPCS_TIR1 BIT(6) /*!< tamper1 interrupt reset */ +#define BKP_TPCS_TPIE1 BIT(7) /*!< tamper1 interrupt enable */ +#define BKP_TPCS_TEF0 BIT(8) /*!< tamper0 event flag */ +#define BKP_TPCS_TIF0 BIT(9) /*!< tamper0 interrupt flag */ +#define BKP_TPCS_TEF1 BIT(14) /*!< tamper1 event flag */ +#define BKP_TPCS_TIF1 BIT(15) /*!< tamper1 interrupt flag */ + +/* BKP_TPCTL1 */ +#define BKP_TPCTL1_TPEN1 BIT(8) /*!< tamper1 detection enable */ +#define BKP_TPCTL1_TPAL1 BIT(9) /*!< tamper1 pin active level */ +#define BKP_TPCTL1_TPM2 BIT(14) /*!< the second waveform detection enable */ +#define BKP_TPCTL1_TPM1 BIT(15) /*!< the first waveform detection enable */ + +/* constants definitions */ +/* tamperx definitions */ +typedef enum +{ + TAMPER_0 = 0, /*!< BKP tamper0 */ + TAMPER_1, /*!< BKP tamper1 */ +}bkp_tamper_enum; + +/* BKP data register number */ +typedef enum +{ + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +}bkp_data_register_enum; + +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* RTC clock output selection */ +#define RTC_CLOCK_DIV64 ((uint16_t)0x0000U) /*!< RTC clock div 64 */ +#define RTC_CLOCK_DIV1 ((uint16_t)0x4000U) /*!< RTC clock div 1 */ + +/* RTC clock calibration direction */ +#define RTC_CLOCK_SLOWED_DOWN ((uint16_t)0x0000U) /*!< RTC clock slow down */ +#define RTC_CLOCK_SPEED_UP ((uint16_t)0x8000U) /*!< RTC clock speed up */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER0 BKP_TPCS_TEF0 /*!< tamper0 event flag */ +#define BKP_FLAG_TAMPER1_WAVEDETECT BKP_TPCS_TEF1 /*!< tamper1/waveform detect event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER0 BKP_TPCS_TIF0 /*!< tamper0 interrupt flag */ +#define BKP_INT_FLAG_TAMPER1_WAVEDETECT BKP_TPCS_TIF1 /*!< tamper1/waveform detect interrupt flag */ + +/* waveform detection mode */ +#define BKP_WAVEFORM_DETECT_1 BKP_TPCTL1_TPM1 /*!< the first waveform detection */ +#define BKP_WAVEFORM_DETECT_2 BKP_TPCTL1_TPM2 /*!< the second waveform detection */ + +/* function declarations */ +/* initialization functions */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_data_read(bkp_data_register_enum register_number); + +/* function configuration */ +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* select RTC output */ +void bkp_rtc_output_select(uint16_t outputsel); +/* RTC clock output selection */ +void bkp_rtc_clock_output_select(uint16_t clocksel); +/* RTC clock calibration direction */ +void bkp_rtc_clock_calibration_direction(uint16_t direction); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(bkp_tamper_enum tamperx); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(bkp_tamper_enum tamperx); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(bkp_tamper_enum tamperx, uint16_t level); + +/* interrupt & flag functions */ +/* enable tamper pin interrupt */ +void bkp_tamper_interrupt_enable(bkp_tamper_enum tamperx); +/* disable tamper pin interrupt */ +void bkp_tamper_interrupt_disable(bkp_tamper_enum tamperx); +/* waveform detect configure */ +void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus newvalue); +/* get BKP flag state */ +FlagStatus bkp_flag_get(uint16_t flag); +/* clear BKP flag state */ +void bkp_flag_clear(uint16_t flag); +/* get BKP interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(uint16_t flag); +/* clear BKP interrupt flag state */ +void bkp_interrupt_flag_clear(uint16_t flag); + +#endif /* GD32F20X_BKP_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h new file mode 100644 index 0000000000..bab172849a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h @@ -0,0 +1,758 @@ +/*! + \file gd32f20x_can.h + \brief definitions for the CAN + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-11-27, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_CAN_H +#define GD32F20X_CAN_H + +#include "gd32f20x.h" + +/* CAN definitions */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ + +/* registers definitions */ +#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ + +/* CAN transmit mailbox bank */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ + +/* CAN filter bank */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ + +/* CAN receive fifo mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ + +/* bits definitions */ +/* CAN_CTL */ +#define CAN_CTL_IWMOD BIT(0) /*!< initial working mode */ +#define CAN_CTL_SLPWMOD BIT(1) /*!< sleep working mode */ +#define CAN_CTL_TFO BIT(2) /*!< transmit FIFO order */ +#define CAN_CTL_RFOD BIT(3) /*!< receive FIFO overwrite disable */ +#define CAN_CTL_ARD BIT(4) /*!< automatic retransmission disable */ +#define CAN_CTL_AWU BIT(5) /*!< automatic wakeup */ +#define CAN_CTL_ABOR BIT(6) /*!< automatic bus-off recovery */ +#define CAN_CTL_TTC BIT(7) /*!< time triggered communication */ +#define CAN_CTL_SWRST BIT(15) /*!< CAN software reset */ +#define CAN_CTL_DFZ BIT(16) /*!< CAN debug freeze */ + +/* CAN_STAT */ +#define CAN_STAT_IWS BIT(0) /*!< initial working state */ +#define CAN_STAT_SLPWS BIT(1) /*!< sleep working state */ +#define CAN_STAT_ERRIF BIT(2) /*!< error interrupt flag*/ +#define CAN_STAT_WUIF BIT(3) /*!< status change interrupt flag of wakeup from sleep working mode */ +#define CAN_STAT_SLPIF BIT(4) /*!< status change interrupt flag of sleep working mode entering */ +#define CAN_STAT_TS BIT(8) /*!< transmitting state */ +#define CAN_STAT_RS BIT(9) /*!< receiving state */ +#define CAN_STAT_LASTRX BIT(10) /*!< last sample value of rx pin */ +#define CAN_STAT_RXL BIT(11) /*!< CAN rx signal */ + +/* CAN_TSTAT */ +#define CAN_TSTAT_MTF0 BIT(0) /*!< mailbox0 transmit finished */ +#define CAN_TSTAT_MTFNERR0 BIT(1) /*!< mailbox0 transmit finished and no error */ +#define CAN_TSTAT_MAL0 BIT(2) /*!< mailbox0 arbitration lost */ +#define CAN_TSTAT_MTE0 BIT(3) /*!< mailbox0 transmit error */ +#define CAN_TSTAT_MST0 BIT(7) /*!< mailbox0 stop transmitting */ +#define CAN_TSTAT_MTF1 BIT(8) /*!< mailbox1 transmit finished */ +#define CAN_TSTAT_MTFNERR1 BIT(9) /*!< mailbox1 transmit finished and no error */ +#define CAN_TSTAT_MAL1 BIT(10) /*!< mailbox1 arbitration lost */ +#define CAN_TSTAT_MTE1 BIT(11) /*!< mailbox1 transmit error */ +#define CAN_TSTAT_MST1 BIT(15) /*!< mailbox1 stop transmitting */ +#define CAN_TSTAT_MTF2 BIT(16) /*!< mailbox2 transmit finished */ +#define CAN_TSTAT_MTFNERR2 BIT(17) /*!< mailbox2 transmit finished and no error */ +#define CAN_TSTAT_MAL2 BIT(18) /*!< mailbox2 arbitration lost */ +#define CAN_TSTAT_MTE2 BIT(19) /*!< mailbox2 transmit error */ +#define CAN_TSTAT_MST2 BIT(23) /*!< mailbox2 stop transmitting */ +#define CAN_TSTAT_NUM BITS(24,25) /*!< mailbox number */ +#define CAN_TSTAT_TME0 BIT(26) /*!< transmit mailbox0 empty */ +#define CAN_TSTAT_TME1 BIT(27) /*!< transmit mailbox1 empty */ +#define CAN_TSTAT_TME2 BIT(28) /*!< transmit mailbox2 empty */ +#define CAN_TSTAT_TMLS0 BIT(29) /*!< last sending priority flag for mailbox0 */ +#define CAN_TSTAT_TMLS1 BIT(30) /*!< last sending priority flag for mailbox1 */ +#define CAN_TSTAT_TMLS2 BIT(31) /*!< last sending priority flag for mailbox2 */ + +/* CAN_RFIFO0 */ +#define CAN_RFIFO0_RFL0 BITS(0,1) /*!< receive FIFO0 length */ +#define CAN_RFIFO0_RFF0 BIT(3) /*!< receive FIFO0 full */ +#define CAN_RFIFO0_RFO0 BIT(4) /*!< receive FIFO0 overfull */ +#define CAN_RFIFO0_RFD0 BIT(5) /*!< receive FIFO0 dequeue */ + +/* CAN_RFIFO1 */ +#define CAN_RFIFO1_RFL1 BITS(0,1) /*!< receive FIFO1 length */ +#define CAN_RFIFO1_RFF1 BIT(3) /*!< receive FIFO1 full */ +#define CAN_RFIFO1_RFO1 BIT(4) /*!< receive FIFO1 overfull */ +#define CAN_RFIFO1_RFD1 BIT(5) /*!< receive FIFO1 dequeue */ + +/* CAN_INTEN */ +#define CAN_INTEN_TMEIE BIT(0) /*!< transmit mailbox empty interrupt enable */ +#define CAN_INTEN_RFNEIE0 BIT(1) /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INTEN_RFFIE0 BIT(2) /*!< receive FIFO0 full interrupt enable */ +#define CAN_INTEN_RFOIE0 BIT(3) /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INTEN_RFNEIE1 BIT(4) /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INTEN_RFFIE1 BIT(5) /*!< receive FIFO1 full interrupt enable */ +#define CAN_INTEN_RFOIE1 BIT(6) /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INTEN_WERRIE BIT(8) /*!< warning error interrupt enable */ +#define CAN_INTEN_PERRIE BIT(9) /*!< passive error interrupt enable */ +#define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ +#define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ +#define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ + +/* CAN_ERR */ +#define CAN_ERR_WERR BIT(0) /*!< warning error */ +#define CAN_ERR_PERR BIT(1) /*!< passive error */ +#define CAN_ERR_BOERR BIT(2) /*!< bus-off error */ +#define CAN_ERR_ERRN BITS(4,6) /*!< error number */ +#define CAN_ERR_TECNT BITS(16,23) /*!< transmit error count */ +#define CAN_ERR_RECNT BITS(24,31) /*!< receive error count */ + +/* CAN_BT */ +#define CAN_BT_BAUDPSC BITS(0,9) /*!< baudrate prescaler */ +#define CAN_BT_BS1 BITS(16,19) /*!< bit segment 1 */ +#define CAN_BT_BS2 BITS(20,22) /*!< bit segment 2 */ +#define CAN_BT_SJW BITS(24,25) /*!< resynchronization jump width */ +#define CAN_BT_LCMOD BIT(30) /*!< loopback communication mode */ +#define CAN_BT_SCMOD BIT(31) /*!< silent communication mode */ + +/* CAN_TMIx */ +#define CAN_TMI_TEN BIT(0) /*!< transmit enable */ +#define CAN_TMI_FT BIT(1) /*!< frame type */ +#define CAN_TMI_FF BIT(2) /*!< frame format */ +#define CAN_TMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_TMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_TMPx */ +#define CAN_TMP_DLENC BITS(0,3) /*!< data length code */ +#define CAN_TMP_TSEN BIT(8) /*!< time stamp enable */ +#define CAN_TMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_TMDATA0x */ +#define CAN_TMDATA0_DB0 BITS(0,7) /*!< transmit data byte 0 */ +#define CAN_TMDATA0_DB1 BITS(8,15) /*!< transmit data byte 1 */ +#define CAN_TMDATA0_DB2 BITS(16,23) /*!< transmit data byte 2 */ +#define CAN_TMDATA0_DB3 BITS(24,31) /*!< transmit data byte 3 */ + +/* CAN_TMDATA1x */ +#define CAN_TMDATA1_DB4 BITS(0,7) /*!< transmit data byte 4 */ +#define CAN_TMDATA1_DB5 BITS(8,15) /*!< transmit data byte 5 */ +#define CAN_TMDATA1_DB6 BITS(16,23) /*!< transmit data byte 6 */ +#define CAN_TMDATA1_DB7 BITS(24,31) /*!< transmit data byte 7 */ + +/* CAN_RFIFOMIx */ +#define CAN_RFIFOMI_FT BIT(1) /*!< frame type */ +#define CAN_RFIFOMI_FF BIT(2) /*!< frame format */ +#define CAN_RFIFOMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_RFIFOMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_RFIFOMPx */ +#define CAN_RFIFOMP_DLENC BITS(0,3) /*!< receive data length code */ +#define CAN_RFIFOMP_FI BITS(8,15) /*!< filter index */ +#define CAN_RFIFOMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_RFIFOMDATA0x */ +#define CAN_RFIFOMDATA0_DB0 BITS(0,7) /*!< receive data byte 0 */ +#define CAN_RFIFOMDATA0_DB1 BITS(8,15) /*!< receive data byte 1 */ +#define CAN_RFIFOMDATA0_DB2 BITS(16,23) /*!< receive data byte 2 */ +#define CAN_RFIFOMDATA0_DB3 BITS(24,31) /*!< receive data byte 3 */ + +/* CAN_RFIFOMDATA1x */ +#define CAN_RFIFOMDATA1_DB4 BITS(0,7) /*!< receive data byte 4 */ +#define CAN_RFIFOMDATA1_DB5 BITS(8,15) /*!< receive data byte 5 */ +#define CAN_RFIFOMDATA1_DB6 BITS(16,23) /*!< receive data byte 6 */ +#define CAN_RFIFOMDATA1_DB7 BITS(24,31) /*!< receive data byte 7 */ + +/* CAN_FCTL */ +#define CAN_FCTL_FLD BIT(0) /*!< filter lock disable */ +#define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ + +/* CAN_FMCFG */ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ + +/* CAN_FSCFG */ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ + +/* CAN_FAFIFO */ +#define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ + +/* CAN_FW */ +#define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ + +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + +/* constants definitions */ +/* define the CAN bit position and its register index offset */ +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +#define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ +#define TSTAT_REG_OFFSET ((uint8_t)0x08U) /*!< TSTAT register offset */ +#define RFIFO0_REG_OFFSET ((uint8_t)0x0CU) /*!< RFIFO0 register offset */ +#define RFIFO1_REG_OFFSET ((uint8_t)0x10U) /*!< RFIFO1 register offset */ +#define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ + +/* CAN flags */ +typedef enum +{ + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + /* flags in TSTAT register */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + /* flags in RFIFO0 register */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + /* flags in RFIFO1 register */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + /* flags in ERR register */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +}can_flag_enum; + +/* CAN interrupt flags */ +typedef enum +{ + /* interrupt flags in STAT register */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +}can_interrupt_flag_enum; + +/* CAN initiliaze parameters structure */ +typedef struct +{ + uint8_t working_mode; /*!< CAN working mode */ + uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ + uint8_t time_segment_1; /*!< time segment 1 */ + uint8_t time_segment_2; /*!< time segment 2 */ + ControlStatus time_triggered; /*!< time triggered communication mode */ + ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ + ControlStatus auto_wake_up; /*!< automatic wake-up mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ + ControlStatus trans_fifo_order; /*!< transmit FIFO order */ + uint16_t prescaler; /*!< baudrate prescaler */ +}can_parameter_struct; + +/* CAN transmit message structure */ +typedef struct +{ + uint32_t tx_sfid; /*!< standard format frame identifier */ + uint32_t tx_efid; /*!< extended format frame identifier */ + uint8_t tx_ff; /*!< format of frame, standard or extended format */ + uint8_t tx_ft; /*!< type of frame, data or remote */ + uint8_t tx_dlen; /*!< data length */ + uint8_t tx_data[8]; /*!< transmit data */ +}can_trasnmit_message_struct; + +/* CAN receive message structure */ +typedef struct +{ + uint32_t rx_sfid; /*!< standard format frame identifier */ + uint32_t rx_efid; /*!< extended format frame identifier */ + uint8_t rx_ff; /*!< format of frame, standard or extended format */ + uint8_t rx_ft; /*!< type of frame, data or remote */ + uint8_t rx_dlen; /*!< data length */ + uint8_t rx_data[8]; /*!< receive data */ + uint8_t rx_fi; /*!< filtering index */ +} can_receive_message_struct; + +/* CAN filter parameters structure */ +typedef struct +{ + uint16_t filter_list_high; /*!< filter list number high bits*/ + uint16_t filter_list_low; /*!< filter list number low bits */ + uint16_t filter_mask_high; /*!< filter mask number high bits */ + uint16_t filter_mask_low; /*!< filter mask number low bits */ + uint16_t filter_fifo_number; /*!< receive FIFO associated with the filter */ + uint16_t filter_number; /*!< filter number */ + uint16_t filter_mode; /*!< filter mode, list or mask */ + uint16_t filter_bits; /*!< filter scale */ + ControlStatus filter_enable; /*!< filter work or not */ +}can_filter_parameter_struct; + +/* CAN errors */ +typedef enum +{ + CAN_ERROR_NONE = 0, /*!< no error */ + CAN_ERROR_FILL, /*!< fill error */ + CAN_ERROR_FORMATE, /*!< format error */ + CAN_ERROR_ACK, /*!< ACK error */ + CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ + CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ + CAN_ERROR_CRC, /*!< CRC error */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ +}can_error_enum; + +/* transmit states */ +typedef enum +{ + CAN_TRANSMIT_FAILED = 0, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4, /*!< no empty mailbox to be used for CAN */ +}can_transmit_state_enum; + +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + +/* CAN baudrate prescaler*/ +#define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) + +/* CAN bit segment 1*/ +#define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) + +/* CAN bit segment 2*/ +#define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) + +/* CAN resynchronization jump width*/ +#define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) + +/* CAN communication mode*/ +#define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) + +/* CAN FDATA high 16 bits */ +#define FDATA_MASK_HIGH(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) + +/* CAN FDATA low 16 bits */ +#define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) + +/* CAN1 filter start bank_number*/ +#define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) + +/* CAN transmit mailbox extended identifier*/ +#define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) + +/* CAN transmit mailbox standard identifier*/ +#define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) + +/* transmit data byte 0 */ +#define TMDATA0_DB0(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 1 */ +#define TMDATA0_DB1(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 2 */ +#define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 3 */ +#define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* transmit data byte 4 */ +#define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 5 */ +#define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 6 */ +#define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 7 */ +#define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* receive mailbox extended identifier*/ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3, 31) + +/* receive mailbox standrad identifier*/ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21, 31) + +/* receive data length */ +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0, 3) + +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8, 15) + +/* receive data byte 0 */ +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* receive data byte 1 */ +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8, 15) + +/* receive data byte 2 */ +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16, 23) + +/* receive data byte 3 */ +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24, 31) + +/* receive data byte 4 */ +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* receive data byte 5 */ +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8, 15) + +/* receive data byte 6 */ +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16, 23) + +/* receive data byte 7 */ +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24, 31) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4, 6) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16, 23) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24, 31) + +/* CAN errors */ +#define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) +#define CAN_ERRN_0 ERR_ERRN(0) /*!< no error */ +#define CAN_ERRN_1 ERR_ERRN(1) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7) /*!< software error */ + +#define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ + +/* CAN communication mode */ +#define CAN_NORMAL_MODE ((uint8_t)0x00U) /*!< normal communication mode */ +#define CAN_LOOPBACK_MODE ((uint8_t)0x01U) /*!< loopback communication mode */ +#define CAN_SILENT_MODE ((uint8_t)0x02U) /*!< silent communication mode */ +#define CAN_SILENT_LOOPBACK_MODE ((uint8_t)0x03U) /*!< loopback and silent communication mode */ + +/* CAN resynchronisation jump width */ +#define CAN_BT_SJW_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_SJW_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_SJW_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_SJW_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ + +/* CAN time segment 1 */ +#define CAN_BT_BS1_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS1_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS1_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS1_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS1_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS1_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS1_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS1_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ +#define CAN_BT_BS1_9TQ ((uint8_t)0x08U) /*!< 9 time quanta */ +#define CAN_BT_BS1_10TQ ((uint8_t)0x09U) /*!< 10 time quanta */ +#define CAN_BT_BS1_11TQ ((uint8_t)0x0AU) /*!< 11 time quanta */ +#define CAN_BT_BS1_12TQ ((uint8_t)0x0BU) /*!< 12 time quanta */ +#define CAN_BT_BS1_13TQ ((uint8_t)0x0CU) /*!< 13 time quanta */ +#define CAN_BT_BS1_14TQ ((uint8_t)0x0DU) /*!< 14 time quanta */ +#define CAN_BT_BS1_15TQ ((uint8_t)0x0EU) /*!< 15 time quanta */ +#define CAN_BT_BS1_16TQ ((uint8_t)0x0FU) /*!< 16 time quanta */ + +/* CAN time segment 2 */ +#define CAN_BT_BS2_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS2_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS2_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS2_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS2_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS2_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS2_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS2_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ + +/* CAN mailbox number */ +#define CAN_MAILBOX0 ((uint8_t)0x00U) /*!< mailbox0 */ +#define CAN_MAILBOX1 ((uint8_t)0x01U) /*!< mailbox1 */ +#define CAN_MAILBOX2 ((uint8_t)0x02U) /*!< mailbox2 */ +#define CAN_NOMAILBOX ((uint8_t)0x03U) /*!< no mailbox empty */ + +/* CAN frame format */ +#define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ +#define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ + +/* CAN receive fifo */ +#define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ +#define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ + +/* frame number of receive fifo */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ + +#define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ +#define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ + +/* CAN working mode */ +#define CAN_MODE_INITIALIZE ((uint8_t)0x01U) /*!< CAN initialize mode */ +#define CAN_MODE_NORMAL ((uint8_t)0x02U) /*!< CAN normal mode */ +#define CAN_MODE_SLEEP ((uint8_t)0x04U) /*!< CAN sleep mode */ + +/* filter bits */ +#define CAN_FILTERBITS_16BIT ((uint8_t)0x00U) /*!< CAN filter 16 bits */ +#define CAN_FILTERBITS_32BIT ((uint8_t)0x01U) /*!< CAN filter 32 bits */ + +/* filter mode */ +#define CAN_FILTERMODE_MASK ((uint8_t)0x00U) /*!< mask mode */ +#define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ + +/* filter 16 bits mask */ +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ + +/* frame type */ +#define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ +#define CAN_FT_REMOTE ((uint32_t)0x00000002U) /*!< remote frame */ + +/* CAN timeout */ +#define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ + +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize CAN */ +void can_deinit(uint32_t can_periph); +/* initialize CAN structure */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +/* CAN filter initialization */ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); + +/* function configuration */ +/* set can1 filter start bank number */ +void can1_filter_start_bank(uint8_t start_bank); +/* enable functions */ +/* CAN debug freeze enable */ +void can_debug_freeze_enable(uint32_t can_periph); +/* CAN debug freeze disable */ +void can_debug_freeze_disable(uint32_t can_periph); +/* CAN time trigger mode enable */ +void can_time_trigger_mode_enable(uint32_t can_periph); +/* CAN time trigger mode disable */ +void can_time_trigger_mode_disable(uint32_t can_periph); + +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); +/* CAN receive message */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); +/* CAN release fifo */ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); +/* CAN receive message length */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); +/* CAN working mode */ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); +/* CAN wakeup from sleep mode */ +ErrStatus can_wakeup(uint32_t can_periph); + +/* CAN get error */ +can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* interrupt & flag functions */ +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); +/* CAN get flag state */ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); +/* CAN clear flag state */ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN get interrupt flag state */ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); +/* CAN clear interrupt flag state */ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag); + +#endif /* GD32F20X_CAN_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h new file mode 100644 index 0000000000..8cf28a7c4a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h @@ -0,0 +1,258 @@ +/*! + \file gd32f20x_cau.h + \brief definitions for the CAU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_CAU_H +#define GD32F20X_CAU_H + +#include "gd32f20x.h" + +/* CAU definitions */ +#define CAU CAU_BASE + +/* registers definitions */ +#define CAU_CTL REG32(CAU + 0x00U) /*!< control register */ +#define CAU_STAT0 REG32(CAU + 0x04U) /*!< status register 0 */ +#define CAU_DI REG32(CAU + 0x08U) /*!< data input register */ +#define CAU_DO REG32(CAU + 0x0CU) /*!< data output register */ +#define CAU_DMAEN REG32(CAU + 0x10U) /*!< DMA enable register */ +#define CAU_INTEN REG32(CAU + 0x14U) /*!< interrupt enable register */ +#define CAU_STAT1 REG32(CAU + 0x18U) /*!< status register 1 */ +#define CAU_INTF REG32(CAU + 0x1CU) /*!< interrupt flag register */ +#define CAU_KEY0H REG32(CAU + 0x20U) /*!< key 0 high register */ +#define CAU_KEY0L REG32(CAU + 0x24U) /*!< key 0 low register */ +#define CAU_KEY1H REG32(CAU + 0x28U) /*!< key 1 high register */ +#define CAU_KEY1L REG32(CAU + 0x2CU) /*!< key 1 low register */ +#define CAU_KEY2H REG32(CAU + 0x30U) /*!< key 2 high register */ +#define CAU_KEY2L REG32(CAU + 0x34U) /*!< key 2 low register */ +#define CAU_KEY3H REG32(CAU + 0x38U) /*!< key 3 high register */ +#define CAU_KEY3L REG32(CAU + 0x3CU) /*!< key 3 low register */ +#define CAU_IV0H REG32(CAU + 0x40U) /*!< initial vector 0 high register */ +#define CAU_IV0L REG32(CAU + 0x44U) /*!< initial vector 0 low register */ +#define CAU_IV1H REG32(CAU + 0x48U) /*!< initial vector 1 high register */ +#define CAU_IV1L REG32(CAU + 0x4CU) /*!< initial vector 1 low register */ + +/* bits definitions */ +/* CAU_CTL */ +#define CAU_CTL_CAUDIR BIT(2) /*!< algorithm direction */ +#define CAU_CTL_ALGM BITS(3,5) /*!< algorithm mode selection */ +#define CAU_CTL_DATAM BITS(6,7) /*!< data swapping selection */ +#define CAU_CTL_KEYM BITS(8,9) /*!< key length selection when aes mode */ +#define CAU_CTL_FFLUSH BIT(14) /*!< FIFO flush */ +#define CAU_CTL_CAUEN BIT(15) /*!< cryptographic module enable */ + +/* CAU_STAT0 */ +#define CAU_STAT0_IEM BIT(0) /*!< IN FIFO empty flag */ +#define CAU_STAT0_INF BIT(1) /*!< IN FIFO not full flag */ +#define CAU_STAT0_ONE BIT(2) /*!< OUT FIFO not empty flag */ +#define CAU_STAT0_OFU BIT(3) /*!< OUT FIFO full flag */ +#define CAU_STAT0_BUSY BIT(4) /*!< busy flag */ + +/* CAU_DI */ +#define CAU_DI_DI BITS(0,31) /*!< data input */ + +/* CAU_DO */ +#define CAU_DO_DO BITS(0,31) /*!< data output */ + +/* CAU_DMAEN */ +#define CAU_DMAEN_DMAIEN BIT(0) /*!< IN FIFO DMA enable */ +#define CAU_DMAEN_DMAOEN BIT(1) /*!< OUT FIFO DMA enable */ + +/* CAU_INTEN */ +#define CAU_INTEN_IINTEN BIT(0) /*!< IN FIFO interrupt enable */ +#define CAU_INTEN_OINTEN BIT(1) /*!< OUT FIFO interrupt enable */ + +/* CAU_STAT1 */ +#define CAU_STAT1_ISTA BIT(0) /*!< flag set when there is less than 4 words in IN FIFO */ +#define CAU_STAT1_OSTA BIT(1) /*!< flag set when there is one or more word in OUT FIFO */ + +/* CAU_INTF */ +#define CAU_INTF_IINTF BIT(0) /*!< IN FIFO interrupt flag */ +#define CAU_INTF_OINTF BIT(1) /*!< OUT FIFO interrupt flag */ + +/* CAU_KEYxH x=0..3 */ +#define CAU_KEYXH_KEYXH BITS(0,31) /*!< the key for des, tdes, aes */ + +/* CAU_KEYxL x=0..3 */ +#define CAU_KEYXL_KEYXL BITS(0,31) /*!< the key for des, tdes, aes */ + +/* CAU_IVxH x=0..1 */ +#define CAU_IVXH_IVXH BITS(0,31) /*!< the initialization vector for des, tdes, aes */ + +/* CAU_IVxL x=0..1 */ +#define CAU_IVXL_IVXL BITS(0,31) /*!< the initialization vector for des, tdes, aes */ + +/* constants definitions */ +/* structure for keys initialization of the cau */ +typedef struct +{ + uint32_t key_0_high; /*!< key 0 high */ + uint32_t key_0_low; /*!< key 0 low */ + uint32_t key_1_high; /*!< key 1 high */ + uint32_t key_1_low; /*!< key 1 low */ + uint32_t key_2_high; /*!< key 2 high */ + uint32_t key_2_low; /*!< key 2 low */ + uint32_t key_3_high; /*!< key 3 high */ + uint32_t key_3_low; /*!< key 3 low */ +}cau_key_parameter_struct; + +/* structure for vectors initialization of the cau */ +typedef struct +{ + uint32_t iv_0_high; /*!< init vector 0 high */ + uint32_t iv_0_low; /*!< init vector 0 low */ + uint32_t iv_1_high; /*!< init vector 1 high */ + uint32_t iv_1_low; /*!< init vector 1 low */ +}cau_iv_parameter_struct; + +/* structure for vectors initialization of the cau */ +typedef struct +{ + uint8_t *input; /*!< pointer to the input buffer */ + uint32_t in_length; /*!< length of the input buffer, + must be a multiple of 8(DES and TDES) or 16(AES) */ + uint8_t *output; /*!< pointer to the returned buffer */ +}cau_text_struct; + +/* cau_ctl register value */ +#define CAU_ENCRYPT ((uint32_t)0x00000000) /*!< encrypt */ +#define CAU_DECRYPT CAU_CTL_CAUDIR /*!< decrypt */ + +#define CTL_ALGM(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) /*!< write value to CAU_CTL_ALGM bit field */ +#define CAU_MODE_TDES_ECB CTL_ALGM(0) /*!< TDES-ECB (3DES Electronic codebook) */ +#define CAU_MODE_TDES_CBC CTL_ALGM(1) /*!< TDES-CBC (3DES Cipher block chaining) */ +#define CAU_MODE_DES_ECB CTL_ALGM(2) /*!< DES-ECB (simple DES Electronic codebook) */ +#define CAU_MODE_DES_CBC CTL_ALGM(3) /*!< DES-CBC (simple DES Cipher block chaining) */ +#define CAU_MODE_AES_ECB CTL_ALGM(4) /*!< AES-ECB (AES Electronic codebook) */ +#define CAU_MODE_AES_CBC CTL_ALGM(5) /*!< AES-CBC (AES Cipher block chaining) */ +#define CAU_MODE_AES_CTR CTL_ALGM(6) /*!< AES-CTR (AES counter mode) */ +#define CAU_MODE_AES_KEY CTL_ALGM(7) /*!< AES decryption key preparation mode */ + +#define CTL_DATAM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to CAU_CTL_DATAM bit field */ +#define CAU_SWAPPING_32BIT CTL_DATAM(0) /*!< no swapping */ +#define CAU_SWAPPING_16BIT CTL_DATAM(1) /*!< half-word swapping */ +#define CAU_SWAPPING_8BIT CTL_DATAM(2) /*!< bytes swapping */ +#define CAU_SWAPPING_1BIT CTL_DATAM(3) /*!< bit swapping */ + +#define CTL_KEYM(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) /*!< write value to CAU_CTL_KEYM bit field */ +#define CAU_KEYSIZE_128BIT CTL_KEYM(0) /*!< 128 bit key length */ +#define CAU_KEYSIZE_192BIT CTL_KEYM(1) /*!< 192 bit key length */ +#define CAU_KEYSIZE_256BIT CTL_KEYM(2) /*!< 256 bit key length */ + +/* cau_stat0 register value */ +#define CAU_FLAG_INFIFO_EMPTY CAU_STAT0_IEM /*!< IN FIFO empty */ +#define CAU_FLAG_INFIFO_NO_FULL CAU_STAT0_INF /*!< IN FIFO is not full */ +#define CAU_FLAG_OUTFIFO_NO_EMPTY CAU_STAT0_ONE /*!< OUT FIFO not empty */ +#define CAU_FLAG_OUTFIFO_FULL CAU_STAT0_OFU /*!< OUT FIFO is full */ +#define CAU_FLAG_BUSY CAU_STAT0_BUSY /*!< the CAU core is busy */ + +/* cau_dmaen register value */ +#define CAU_DMA_INFIFO CAU_DMAEN_DMAIEN /*!< DMA input enable */ +#define CAU_DMA_OUTFIFO CAU_DMAEN_DMAOEN /*!< DMA output enable */ + +/* cau_inten register value */ +#define CAU_INT_INFIFO CAU_INTEN_IINTEN /*!< IN FIFO Interrupt */ +#define CAU_INT_OUTFIFO CAU_INTEN_OINTEN /*!< OUT FIFO Interrupt */ + +/* cau_stat1 register value */ +#define CAU_FLAG_INFIFO (CAU_STAT1_ISTA | ((uint32_t)0x00000020U)) /*!< IN FIFO flag status */ +#define CAU_FLAG_OUTFIFO (CAU_STAT1_OSTA | ((uint32_t)0x00000020U)) /*!< OUT FIFO flag status */ + +/* cau_intf register value */ +#define CAU_INT_FLAG_INFIFO CAU_INTF_IINTF /*!< IN FIFO interrupt status */ +#define CAU_INT_FLAG_OUTFIFO CAU_INTF_OINTF /*!< OUT FIFO interrupt status */ + +/* function declarations */ +/* initialization functions */ +/* reset the CAU peripheral */ +void cau_deinit(void); +/* enable the CAU peripheral */ +void cau_enable(void); +/* disable the CAU peripheral */ +void cau_disable(void); +/* enable the CAU DMA interface */ +void cau_dma_enable(uint32_t dma_req); +/* disable the CAU DMA interface */ +void cau_dma_disable(uint32_t dma_req); +/* initialize the CAU peripheral */ +void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping); +/* configure key size if used AES algorithm */ +void cau_aes_keysize_config(uint32_t key_size); +/* initialize the key parameters */ +void cau_key_init(cau_key_parameter_struct* key_initpara); +/* initialize the structure cau_key_initpara */ +void cau_key_parameter_init(cau_key_parameter_struct* key_initpara); +/* initialize the vectors parameters */ +void cau_iv_init(cau_iv_parameter_struct* iv_initpara); +/* initialize the vectors parameters */ +void cau_iv_parameter_init(cau_iv_parameter_struct* iv_initpara); +/* flush the IN and OUT FIFOs */ +void cau_fifo_flush(void); +/* return whether CAU peripheral is enabled or disabled */ +ControlStatus cau_enable_state_get(void); +/* write data to the IN FIFO */ +void cau_data_write(uint32_t data); +/* return the last data entered into the output FIFO */ +uint32_t cau_data_read(void); + +/* function configuration */ +/* calculate digest in HASH mode */ +/* encrypt and decrypt using AES in ECB mode */ +ErrStatus cau_aes_ecb(uint32_t algo_dir, uint8_t *key, uint16_t keysize, cau_text_struct *text); +/* encrypt and decrypt using AES in CBC mode */ +ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text); +/* encrypt and decrypt using AES in CTR mode */ +ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text); +/* encrypt and decrypt using TDES in ECB mode */ +ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text); +/* encrypt and decrypt using TDES in CBC mode */ +ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text); +/* encrypt and decrypt using DES in ECB mode */ +ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text); +/* encrypt and decrypt using DES in CBC mode */ +ErrStatus cau_des_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text); + +/* interrupt & flag functions */ +/* get the CAU flag status */ +FlagStatus cau_flag_get(uint32_t flag); +/* enable the CAU interrupts */ +void cau_interrupt_enable(uint32_t interrupt); +/* disable the CAU interrupts */ +void cau_interrupt_disable(uint32_t interrupt); +/* get the interrupt flag */ +FlagStatus cau_interrupt_flag_get(uint32_t int_flag); + +#endif /* GD32F20X_CAU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h new file mode 100644 index 0000000000..90556a8658 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h @@ -0,0 +1,80 @@ +/*! + \file gd32f20x_crc.h + \brief definitions for the CRC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_CRC_H +#define GD32F20X_CRC_H + +#include "gd32f20x.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0,31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0,7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + +/* function declarations */ +/* initialization functions */ +/* deinit CRC calculation unit */ +void crc_deinit(void); +/* reset data register to the value of initialization data register */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* function configuration */ +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size); + +#endif /* GD32F20X_CRC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h new file mode 100644 index 0000000000..b0d5100b0e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h @@ -0,0 +1,247 @@ +/*! + \file gd32f20x_dac.h + \brief definitions for the DAC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DAC_H +#define GD32F20X_DAC_H + +#include "gd32f20x.h" + +/* DACx(x=0,1) definitions */ +#define DAC DAC_BASE +#define DAC0 0U +#define DAC1 1U + +/* registers definitions */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ + +/* bits definitions */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ + +/* DAC_SWT */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ + +/* DAC0_R12DH */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ + +/* DAC0_L12DH */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ + +/* DAC0_R8DH */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ + +/* DAC1_R12DH */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ + +/* DAC1_L12DH */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ + +/* DAC1_R8DH */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ + +/* DACC_R12DH */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ + +/* DACC_L12DH */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ + +/* DACC_R8DH */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ + +/* DAC0_DO */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ + +/* DAC1_DO */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ + +/* constants definitions */ +/* DAC trigger source */ +#define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#define DAC_TRIGGER_T2_TRGO CTL_DTSEL(1) /*!< TIMER2 TRGO */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ + +/* DAC noise wave mode */ +#define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ + +/* DAC noise wave bit width */ +#define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ + +/* unmask LFSR bits in DAC LFSR noise mode */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ + +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ + +/* DAC data alignment */ +#define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12b alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12b alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8b alignment */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DAC */ +void dac_deinit(void); +/* enable DAC */ +void dac_enable(uint32_t dac_periph); +/* disable DAC */ +void dac_disable(uint32_t dac_periph); +/* enable DAC DMA */ +void dac_dma_enable(uint32_t dac_periph); +/* disable DAC DMA */ +void dac_dma_disable(uint32_t dac_periph); +/* enable DAC output buffer */ +void dac_output_buffer_enable(uint32_t dac_periph); +/* disable DAC output buffer */ +void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* function configuration */ +/* DAC trigger configuration */ +/* enable DAC trigger */ +void dac_trigger_enable(uint32_t dac_periph); +/* disable DAC trigger */ +void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* enable DAC software trigger */ +void dac_software_trigger_enable(uint32_t dac_periph); +/* disable DAC software trigger */ +void dac_software_trigger_disable(uint32_t dac_periph); + +/* DAC wave mode configuration */ +/* configure DAC wave mode */ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); +/* configure DAC wave bit width */ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); +/* configure DAC LFSR noise mode */ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); +/* configure DAC triangle noise mode */ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); + +/* DAC concurrent mode configuration */ +/* enable DAC concurrent mode */ +void dac_concurrent_enable(void); +/* disable DAC concurrent mode */ +void dac_concurrent_disable(void); +/* enable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_enable(void); +/* disable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_disable(void); +/* enable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_enable(void); +/* disable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); + +#endif /* GD32F20X_DAC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h new file mode 100644 index 0000000000..39c37464d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h @@ -0,0 +1,146 @@ +/*! + \file gd32f20x_dbg.h + \brief definitions for the DBG + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2020-12-14, V2.2.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DBG_H +#define GD32F20X_DBG_H + +#include "gd32f20x.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL REG32(DBG + 0x04U) /*!< DBG control register */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ + +/* DBG_CTL */ +#define DBG_CTL_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL_TRACE_IOEN BIT(5) /*!< enable trace pin assignment */ +#define DBG_CTL_TRACE_MODE BITS(6,7) /*!< trace pin mode selection */ +#define DBG_CTL_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL_TIMER7_HOLD BIT(17) /*!< hold TIMER7 counter when core is halted */ +#define DBG_CTL_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#define DBG_CTL_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ +#define DBG_CTL_TIMER11_HOLD BIT(25) /*!< hold TIMER11 counter when core is halted */ +#define DBG_CTL_TIMER12_HOLD BIT(26) /*!< hold TIMER12 counter when core is halted */ +#define DBG_CTL_TIMER13_HOLD BIT(27) /*!< hold TIMER13 counter when core is halted */ +#define DBG_CTL_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ +#define DBG_CTL_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ +#define DBG_CTL_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ + +/* constants definitions */ +/* debug hold when core is halted */ +typedef enum +{ + DBG_FWDGT_HOLD = BIT(8), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = BIT(9), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = BIT(10), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = BIT(11), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = BIT(12), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = BIT(13), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = BIT(14), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = BIT(15), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = BIT(16), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = BIT(17), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = BIT(18), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = BIT(19), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = BIT(20), /*!< hold TIMER6 counter when core is halted */ + DBG_CAN1_HOLD = BIT(21), /*!< debug CAN1 kept when core is halted */ + DBG_TIMER11_HOLD = BIT(25), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = BIT(26), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = BIT(27), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = BIT(28), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = BIT(29), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = BIT(30), /*!< hold TIMER10 counter when core is halted */ +}dbg_periph_enum; + +/* DBG low power mode configurations */ +#define DBG_LOW_POWER_SLEEP DBG_CTL_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* DBG_CTL0_TRACE_MODE configurations */ +#define CTL_TRACE_MODE(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) +#define TRACE_MODE_ASYNC CTL_TRACE_MODE(0) /*!< trace pin used for async mode */ +#define TRACE_MODE_SYNC_DATASIZE_1 CTL_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ +#define TRACE_MODE_SYNC_DATASIZE_2 CTL_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ +#define TRACE_MODE_SYNC_DATASIZE_4 CTL_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ + +/* function declarations */ +/* initialization functions */ +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* function configuration */ +/* low power behavior configuration */ +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* peripheral behavior configuration */ +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +/* trace pin assignment configuration */ +/* enable trace pin assignment */ +void dbg_trace_pin_enable(void); +/* disable trace pin assignment */ +void dbg_trace_pin_disable(void); +/* set trace pin mode */ +void dbg_trace_pin_mode_set(uint32_t trace_mode); + +#endif /* GD32F20X_DBG_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h new file mode 100644 index 0000000000..868a64364d --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h @@ -0,0 +1,236 @@ +/*! + \file gd32f20x_dci.h + \brief definitions for the DCI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DCI_H +#define GD32F20X_DCI_H + +#include "gd32f20x.h" + +/* DCI definitions */ +#define DCI DCI_BASE + +/* registers definitions */ +#define DCI_CTL REG32(DCI + 0x00U) /*!< DCI control register */ +#define DCI_STAT0 REG32(DCI + 0x04U) /*!< DCI status register 0 */ +#define DCI_STAT1 REG32(DCI + 0x08U) /*!< DCI status register 1 */ +#define DCI_INTEN REG32(DCI + 0x0CU) /*!< DCI interrupt enable register */ +#define DCI_INTF REG32(DCI + 0x10U) /*!< DCI interrupt flag register */ +#define DCI_INTC REG32(DCI + 0x14U) /*!< DCI interrupt clear register */ +#define DCI_SC REG32(DCI + 0x18U) /*!< DCI synchronization codes register */ +#define DCI_SCUMSK REG32(DCI + 0x1CU) /*!< DCI synchronization codes unmask register */ +#define DCI_CWSPOS REG32(DCI + 0x20U) /*!< DCI cropping window start position register */ +#define DCI_CWSZ REG32(DCI + 0x24U) /*!< DCI cropping window size register */ +#define DCI_DATA REG32(DCI + 0x28U) /*!< DCI data register */ + +/* bits definitions */ +/* DCI_CTL */ +#define DCI_CTL_CAP BIT(0) /*!< capture enable */ +#define DCI_CTL_SNAP BIT(1) /*!< snapshot mode */ +#define DCI_CTL_WDEN BIT(2) /*!< window enable */ +#define DCI_CTL_JM BIT(3) /*!< JPEG mode */ +#define DCI_CTL_ESM BIT(4) /*!< embedded synchronous mode */ +#define DCI_CTL_CKS BIT(5) /*!< clock polarity selection */ +#define DCI_CTL_HPS BIT(6) /*!< horizontal polarity selection */ +#define DCI_CTL_VPS BIT(7) /*!< vertical polarity selection */ +#define DCI_CTL_FR BITS(8,9) /*!< frame rate */ +#define DCI_CTL_DCIF BITS(10,11) /*!< digital camera interface format */ +#define DCI_CTL_DCIEN BIT(14) /*!< DCI enable */ + +/* DCI_STAT0 */ +#define DCI_STAT0_HS BIT(0) /*!< HS line status */ +#define DCI_STAT0_VS BIT(1) /*!< VS line status */ +#define DCI_STAT0_FV BIT(2) /*!< FIFO valid */ + +/* DCI_STAT1 */ +#define DCI_STAT1_EFF BIT(0) /*!< end of frame flag */ +#define DCI_STAT1_OVRF BIT(1) /*!< FIFO overrun flag */ +#define DCI_STAT1_ESEF BIT(2) /*!< embedded synchronous error flag */ +#define DCI_STAT1_VSF BIT(3) /*!< vsync flag */ +#define DCI_STAT1_ELF BIT(4) /*!< end of line flag */ + +/* DCI_INTEN */ +#define DCI_INTEN_EFIE BIT(0) /*!< end of frame interrupt enable */ +#define DCI_INTEN_OVRIE BIT(1) /*!< FIFO overrun interrupt enable */ +#define DCI_INTEN_ESEIE BIT(2) /*!< embedded synchronous error interrupt enable */ +#define DCI_INTEN_VSIE BIT(3) /*!< vsync interrupt enable */ +#define DCI_INTEN_ELIE BIT(4) /*!< end of line interrupt enable */ + +/* DCI_INTF */ +#define DCI_INTF_EFIF BIT(0) /*!< end of frame interrupt flag */ +#define DCI_INTF_OVRIF BIT(1) /*!< FIFO overrun interrupt flag */ +#define DCI_INTF_ESEIF BIT(2) /*!< embedded synchronous error interrupt flag */ +#define DCI_INTF_VSIF BIT(3) /*!< vsync interrupt flag */ +#define DCI_INTF_ELIF BIT(4) /*!< end of line interrupt flag */ + +/* DCI_INTC */ +#define DCI_INTC_EFFC BIT(0) /*!< clear end of frame flag */ +#define DCI_INTC_OVRFC BIT(1) /*!< clear FIFO overrun flag */ +#define DCI_INTC_ESEFC BIT(2) /*!< clear embedded synchronous error flag */ +#define DCI_INTC_VSFC BIT(3) /*!< vsync flag clear */ +#define DCI_INTC_ELFC BIT(4) /*!< end of line flag clear */ + +/* DCI_SC */ +#define DCI_SC_FS BITS(0,7) /*!< frame start code in embedded synchronous mode */ +#define DCI_SC_LS BITS(8,15) /*!< line start code in embedded synchronous mode */ +#define DCI_SC_LE BITS(16,23) /*!< line end code in embedded synchronous mode */ +#define DCI_SC_FE BITS(24,31) /*!< frame end code in embedded synchronous mode */ + +/* DCI_SCUNMSK */ +#define DCI_SCUMSK_FSM BITS(0,7) /*!< frame start code unmask bits in embedded synchronous mode */ +#define DCI_SCUMSK_LSM BITS(8,15) /*!< line start code unmask bits in embedded synchronous mode */ +#define DCI_SCUMSK_LEM BITS(16,23) /*!< line end code unmask bits in embedded synchronous mode */ +#define DCI_SCUMSK_FEM BITS(24,31) /*!< frame end code unmask bits in embedded synchronous mode */ + +/* DCI_CWSPOS */ +#define DCI_CWSPOS_WHSP BITS(0,13) /*!< window horizontal start position */ +#define DCI_CWSPOS_WVSP BITS(16,28) /*!< window vertical start position */ + +/* DCI_CWSZ */ +#define DCI_CWSZ_WHSZ BITS(0,13) /*!< window horizontal size */ +#define DCI_CWSZ_WVSZ BITS(16,29) /*!< window vertical size */ + +/* constants definitions */ +/* DCI parameter structure definitions */ +typedef struct +{ + uint32_t capture_mode; /*!< DCI capture mode: continuous or snapshot */ + uint32_t clock_polarity; /*!< clock polarity selection */ + uint32_t hsync_polarity; /*!< horizontal polarity selection */ + uint32_t vsync_polarity; /*!< vertical polarity selection */ + uint32_t frame_rate; /*!< frame capture rate */ + uint32_t interface_format; /*!< digital camera interface format */ +}dci_parameter_struct; + +#define DCI_CAPTURE_MODE_CONTINUOUS ((uint32_t)0x00000000U) /*!< continuous capture mode */ +#define DCI_CAPTURE_MODE_SNAPSHOT DCI_CTL_SNAP /*!< snapshot capture mode */ + +#define DCI_CK_POLARITY_FALLING ((uint32_t)0x00000000U) /*!< capture at falling edge */ +#define DCI_CK_POLARITY_RISING DCI_CTL_CKS /*!< capture at rising edge */ + +#define DCI_HSYNC_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level during blanking period */ +#define DCI_HSYNC_POLARITY_HIGH DCI_CTL_HPS /*!< high level during blanking period */ + +#define DCI_VSYNC_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level during blanking period */ +#define DCI_VSYNC_POLARITY_HIGH DCI_CTL_VPS /*!< high level during blanking period*/ + +#define CTL_FR(regval) (BITS(8,9)&((uint32_t)(regval) << 8U)) +#define DCI_FRAME_RATE_ALL CTL_FR(0) /*!< capture all frames */ +#define DCI_FRAME_RATE_1_2 CTL_FR(1) /*!< capture one in 2 frames */ +#define DCI_FRAME_RATE_1_4 CTL_FR(2) /*!< capture one in 4 frames */ + +#define CTL_DCIF(regval) (BITS(10,11)&((uint32_t)(regval) << 10U)) +#define DCI_INTERFACE_FORMAT_8BITS CTL_DCIF(0) /*!< 8-bit data on every pixel clock */ +#define DCI_INTERFACE_FORMAT_10BITS CTL_DCIF(1) /*!< 10-bit data on every pixel clock */ +#define DCI_INTERFACE_FORMAT_12BITS CTL_DCIF(2) /*!< 12-bit data on every pixel clock */ +#define DCI_INTERFACE_FORMAT_14BITS CTL_DCIF(3) /*!< 14-bit data on every pixel clock */ + +/* DCI interrupt constants definitions */ +#define DCI_INT_EF BIT(0) /*!< end of frame interrupt */ +#define DCI_INT_OVR BIT(1) /*!< FIFO overrun interrupt */ +#define DCI_INT_ESE BIT(2) /*!< embedded synchronous error interrupt */ +#define DCI_INT_VSYNC BIT(3) /*!< vsync interrupt */ +#define DCI_INT_EL BIT(4) /*!< end of line interrupt */ + +/* DCI interrupt flag definitions */ +#define DCI_INT_FLAG_EF BIT(0) /*!< end of frame interrupt flag */ +#define DCI_INT_FLAG_OVR BIT(1) /*!< FIFO overrun interrupt flag */ +#define DCI_INT_FLAG_ESE BIT(2) /*!< embedded synchronous error interrupt flag */ +#define DCI_INT_FLAG_VSYNC BIT(3) /*!< vsync interrupt flag */ +#define DCI_INT_FLAG_EL BIT(4) /*!< end of line interrupt flag */ + +/* DCI flag definitions */ +#define DCI_FLAG_HS DCI_STAT0_HS /*!< HS line status */ +#define DCI_FLAG_VS DCI_STAT0_VS /*!< VS line status */ +#define DCI_FLAG_FV DCI_STAT0_FV /*!< FIFO valid */ +#define DCI_FLAG_EF (DCI_STAT1_EFF | BIT(31)) /*!< end of frame flag */ +#define DCI_FLAG_OVR (DCI_STAT1_OVRF | BIT(31)) /*!< FIFO overrun flag */ +#define DCI_FLAG_ESE (DCI_STAT1_ESEF | BIT(31)) /*!< embedded synchronous error flag */ +#define DCI_FLAG_VSYNC (DCI_STAT1_VSF | BIT(31)) /*!< vsync flag */ +#define DCI_FLAG_EL (DCI_STAT1_ELF | BIT(31)) /*!< end of line flag */ + +/* function declarations */ +/* initialization functions */ +/* DCI deinit */ +void dci_deinit(void); +/* initialize DCI registers */ +void dci_init(dci_parameter_struct* dci_struct); + +/* enable DCI function */ +void dci_enable(void); +/* disable DCI function */ +void dci_disable(void); +/* enable DCI capture */ +void dci_capture_enable(void); +/* disable DCI capture */ +void dci_capture_disable(void); +/* enable DCI jpeg mode */ +void dci_jpeg_enable(void); +/* disable DCI jpeg mode */ +void dci_jpeg_disable(void); + +/* function configuration */ +/* enable cropping window function */ +void dci_crop_window_enable(void); +/* disable cropping window function */ +void dci_crop_window_disable(void); +/* configure DCI cropping window */ +void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height); + +/* enable embedded synchronous mode */ +void dci_embedded_sync_enable(void); +/* disable embedded synchronous mode */ +void dci_embedded_sync_disable(void); +/* configure synchronous codes in embedded synchronous mode */ +void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end); +/* configure synchronous codes unmask in embedded synchronous mode */ +void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end); +/* read DCI data register */ +uint32_t dci_data_read(void); + +/* interrupt & flag functions */ +/* get specified flag */ +FlagStatus dci_flag_get(uint32_t flag); +/* enable specified DCI interrupt */ +void dci_interrupt_enable(uint32_t interrupt); +/* disable specified DCI interrupt */ +void dci_interrupt_disable(uint32_t interrupt); +/* get specified interrupt flag */ +FlagStatus dci_interrupt_flag_get(uint32_t int_flag); +/* clear specified interrupt flag */ +void dci_interrupt_flag_clear(uint32_t int_flag); + +#endif /* GD32F20X_DCI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h new file mode 100644 index 0000000000..bc52e95db5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h @@ -0,0 +1,300 @@ +/*! + \file gd32f20x_dma.h + \brief definitions for the DMA + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DMA_H +#define GD32F20X_DMA_H + +#include "gd32f20x.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +#define DMA_ACFG REG32((DMA1) + 0x300U) /*!< DMA additional configuration register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT, x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ + +/* DMA_CHxPADDR, x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ + +/* DMA_CHxMADDR, x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ + +/* DMA_ACFG */ +#define DMA_ACFG_FD_CH5EN BIT(5) /*!< enable bit for DMA1 channel 5 Full_Data transfer mode */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum +{ + DMA_CH0 = 0, /*!< DMA channel 0 */ + DMA_CH1, /*!< DMA channel 1 */ + DMA_CH2, /*!< DMA channel 2 */ + DMA_CH3, /*!< DMA channel 3 */ + DMA_CH4, /*!< DMA channel 4 */ + DMA_CH5, /*!< DMA channel 5 */ + DMA_CH6 /*!< DMA channel 6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ +#define DMA_ACFG_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA additional configuration register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x00U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x01U) /*!< read from memory and write to peripheral */ + +/* circular mode */ +#define DMA_CIRCULAR_MODE_DISABLE ((uint32_t)0x00000000U) /*!< circular mode disable */ +#define DMA_CIRCULAR_MODE_ENABLE ((uint32_t)0x00000001U) /*!< circular mode enable */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8,9) & ((regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0U) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1U) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2U) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10,11) & ((regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0U) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1U) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2U) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12,13) & ((regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0U) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1U) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2U) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3U) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) /*!< disable memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) /*!< enable memory to memory mode */ + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA structure with the default values */ +void dma_struct_para_init(dma_parameter_struct* init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increment algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increment algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increment algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increment algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the flag of a DMA channel */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the interrupt flag of a DMA channel */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +/* enable the DMA1 channel 5 Full_Data transfer mode */ +void dma_1_channel_5_fulldata_transfer_enable(void); +/* disable the DMA1 channel 5 Full_Data transfer mode */ +void dma_1_channel_5_fulldata_transfer_disable(void); + +#endif /* GD32F20X_DMA_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h new file mode 100644 index 0000000000..d18dd4761b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h @@ -0,0 +1,1499 @@ +/*! + \file gd32f20x_enet.h + \brief definitions for the ENET + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_ENET_H +#define GD32F20X_ENET_H + +#include "gd32f20x.h" +#include + +#define IF_USE_EXTERNPHY_LIB 0 +#if (1 == IF_USE_EXTERNPHY_LIB) +#include "phy.h" +#endif + +#ifndef ENET_RXBUF_NUM +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ +#endif + +#ifndef ENET_TXBUF_NUM +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ +#endif + +#ifndef ENET_RXBUF_SIZE +#define ENET_RXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet receive buffer size */ +#endif + +#ifndef ENET_TXBUF_SIZE +#define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ +#endif + +/* #define USE_DELAY */ + +#ifndef _PHY_H_ +#define DP83848 0 +#define LAN8700 1 +#define PHY_TYPE DP83848 + +#define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ + +/* PHY read write timeouts */ +#define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ +#define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ + +/* PHY delay */ +#define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ +#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ + +/* PHY register address */ +#define PHY_REG_BCR 0U /*!< tranceiver basic control register */ +#define PHY_REG_BSR 1U /*!< tranceiver basic status register */ + +/* PHY basic control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ + +#if(PHY_TYPE == LAN8700) +#define PHY_SR 31U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#elif(PHY_TYPE == DP83848) +#define PHY_SR 16U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#endif /* PHY_TYPE */ + +#endif /* _PHY_H_ */ + + +/* ENET definitions */ +#define ENET ENET_BASE + +/* registers definitions */ +#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ +#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ + +/* bits definitions */ +/* ENET_MAC_CFG */ +#define ENET_MAC_CFG_REN BIT(2) /*!< receiver enable */ +#define ENET_MAC_CFG_TEN BIT(3) /*!< transmitter enable */ +#define ENET_MAC_CFG_DFC BIT(4) /*!< defferal check */ +#define ENET_MAC_CFG_BOL BITS(5,6) /*!< back-off limit */ +#define ENET_MAC_CFG_APCD BIT(7) /*!< automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD BIT(9) /*!< retry disable */ +#define ENET_MAC_CFG_IPFCO BIT(10) /*!< IP frame checksum offload */ +#define ENET_MAC_CFG_DPM BIT(11) /*!< duplex mode */ +#define ENET_MAC_CFG_LBM BIT(12) /*!< loopback mode */ +#define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ +#define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ +#define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ +#define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ + +/* ENET_MAC_FRMF */ +#define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ +#define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + +/* ENET_MAC_HLH */ +#define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ + +/* ENET_MAC_HLL */ +#define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ + +/* ENET_MAC_PHY_CTL */ +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + +/* ENET_MAC_PHY_DATA */ +#define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ + +/* ENET_MAC_FCTL */ +#define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ +#define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ + +/* ENET_MAC_FCTH */ +#define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ +#define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ + +/* ENET_MAC_VLT */ +#define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ + +/* ENET_MAC_RWFF */ +#define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ + +/* ENET_MAC_WUM */ +#define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ +#define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ +#define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ +#define ENET_MAC_WUM_MPKR BIT(5) /*!< magic packet received */ +#define ENET_MAC_WUM_WUFR BIT(6) /*!< wakeup frame received */ +#define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ +#define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ + +/* ENET_MAC_INTF */ +#define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ +#define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ +#define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ +#define ENET_MAC_INTF_MSCT BIT(6) /*!< MSC transmit status */ +#define ENET_MAC_INTF_TMST BIT(9) /*!< timestamp trigger status */ + +/* ENET_MAC_INTMSK */ +#define ENET_MAC_INTMSK_WUMIM BIT(3) /*!< WUM interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM BIT(9) /*!< timestamp trigger interrupt mask */ + +/* ENET_MAC_ADDR0H */ +#define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ +#define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ + +/* ENET_MAC_ADDR0L */ +#define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ + +/* ENET_MAC_ADDR1H */ +#define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR1L */ +#define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ + +/* ENET_MAC_ADDR2H */ +#define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ +#define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR2L */ +#define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ + +/* ENET_MAC_ADDR3H */ +#define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ +#define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR3H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR3H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR3L */ +#define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ + +/* ENET_MSC_CTL */ +#define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ +#define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ +#define ENET_MSC_CTL_RTOR BIT(2) /*!< reset on read */ +#define ENET_MSC_CTL_MCFZ BIT(3) /*!< MSC counter freeze */ + +/* ENET_MSC_RINTF */ +#define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ +#define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ +#define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ + +/* ENET_MSC_TINTF */ +#define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ +#define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ +#define ENET_MSC_TINTF_TGF BIT(21) /*!< transmitted good frames */ + +/* ENET_MSC_RINTMSK */ +#define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ + +/* ENET_MSC_TINTMSK */ +#define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ + +/* ENET_MSC_SCCNT */ +#define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ + +/* ENET_MSC_MSCCNT */ +#define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ + +/* ENET_MSC_TGFCNT */ +#define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ + +/* ENET_MSC_RFCECNT */ +#define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ + +/* ENET_MSC_RFAECNT */ +#define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ + +/* ENET_MSC_RGUFCNT */ +#define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ + +/* ENET_PTP_TSCTL */ +#define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI BIT(2) /*!< timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU BIT(3) /*!< timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN BIT(4) /*!< timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU BIT(5) /*!< timestamp addend register update */ + +/* ENET_PTP_SSINC */ +#define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ + +/* ENET_PTP_TSH */ +#define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ + +/* ENET_PTP_TSL */ +#define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ +#define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ + +/* ENET_PTP_TSUH */ +#define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ + +/* ENET_PTP_TSUL */ +#define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ +#define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ + +/* ENET_PTP_TSADDEND */ +#define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ + +/* ENET_PTP_ETH */ +#define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ + +/* ENET_PTP_ETL */ +#define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ + +/* ENET_DMA_BCTL */ +#define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ +#define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ +#define ENET_DMA_BCTL_DPSL BITS(2,6) /*!< descriptor skip length */ +#define ENET_DMA_BCTL_PGBL BITS(8,13) /*!< programmable burst length */ +#define ENET_DMA_BCTL_RTPR BITS(14,15) /*!< RxDMA and TxDMA transfer priority ratio */ +#define ENET_DMA_BCTL_FB BIT(16) /*!< fixed Burst */ +#define ENET_DMA_BCTL_RXDP BITS(17,22) /*!< RxDMA PGBL */ +#define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ +#define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ +#define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ + +/* ENET_DMA_TPEN */ +#define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ + +/* ENET_DMA_RPEN */ +#define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ + +/* ENET_DMA_RDTADDR */ +#define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ + +/* ENET_DMA_TDTADDR */ +#define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ + +/* ENET_DMA_STAT */ +#define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ +#define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ +#define ENET_DMA_STAT_TBU BIT(2) /*!< transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT BIT(3) /*!< transmit jabber timeout status */ +#define ENET_DMA_STAT_RO BIT(4) /*!< receive overflow status */ +#define ENET_DMA_STAT_TU BIT(5) /*!< transmit underflow status */ +#define ENET_DMA_STAT_RS BIT(6) /*!< receive status */ +#define ENET_DMA_STAT_RBU BIT(7) /*!< receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS BIT(8) /*!< receive process stopped status */ +#define ENET_DMA_STAT_RWT BIT(9) /*!< receive watchdog timeout status */ +#define ENET_DMA_STAT_ET BIT(10) /*!< early transmit status */ +#define ENET_DMA_STAT_FBE BIT(13) /*!< fatal bus error status */ +#define ENET_DMA_STAT_ER BIT(14) /*!< early receive status */ +#define ENET_DMA_STAT_AI BIT(15) /*!< abnormal interrupt summary */ +#define ENET_DMA_STAT_NI BIT(16) /*!< normal interrupt summary */ +#define ENET_DMA_STAT_RP BITS(17,19) /*!< receive process state */ +#define ENET_DMA_STAT_TP BITS(20,22) /*!< transmit process state */ +#define ENET_DMA_STAT_EB BITS(23,25) /*!< error bits status */ +#define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ +#define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ +#define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ + +/* ENET_DMA_CTL */ +#define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ +#define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ +#define ENET_DMA_CTL_RTHC BITS(3,4) /*!< receive threshold control */ +#define ENET_DMA_CTL_FUF BIT(6) /*!< forward undersized good frames */ +#define ENET_DMA_CTL_FERF BIT(7) /*!< forward error frames */ +#define ENET_DMA_CTL_STE BIT(13) /*!< start/stop transmission enable */ +#define ENET_DMA_CTL_TTHC BITS(14,16) /*!< transmit threshold control */ +#define ENET_DMA_CTL_FTF BIT(20) /*!< flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD BIT(21) /*!< transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ + +/* ENET_DMA_INTEN */ +#define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE BIT(2) /*!< transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE BIT(3) /*!< transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE BIT(4) /*!< receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE BIT(5) /*!< transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE BIT(6) /*!< receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE BIT(7) /*!< receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE BIT(8) /*!< receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE BIT(9) /*!< receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE BIT(10) /*!< early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE BIT(13) /*!< fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ + +/* ENET_DMA_MFBOCNT */ +#define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ +#define ENET_DMA_MFBOCNT_OBMFC BIT(16) /*!< overflow bit for missed frame counter */ +#define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ +#define ENET_DMA_MFBOCNT_OBFOC BIT(28) /*!< overflow bit for FIFO overflow counter */ + +/* ENET_DMA_CTDADDR */ +#define ENET_DMA_CTDADDR_TDAP BITS(0,31) /*!< transmit descriptor address pointer */ + +/* ENET_DMA_CRDADDR */ +#define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ + +/* ENET_DMA_CTBADDR */ +#define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ + +/* ENET_DMA_CRBADDR */ +#define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ + +/* ENET DMA Tx descriptor TDES0 */ +#define ENET_TDES0_DB BIT(0) /*!< deferred */ +#define ENET_TDES0_UFE BIT(1) /*!< underflow error */ +#define ENET_TDES0_EXD BIT(2) /*!< excessive deferral */ +#define ENET_TDES0_COCNT BITS(3,6) /*!< collision count */ +#define ENET_TDES0_VFRM BIT(7) /*!< VLAN frame */ +#define ENET_TDES0_ECO BIT(8) /*!< excessive collision */ +#define ENET_TDES0_LCO BIT(9) /*!< late collision */ +#define ENET_TDES0_NCA BIT(10) /*!< no carrier */ +#define ENET_TDES0_LCA BIT(11) /*!< loss of carrier */ +#define ENET_TDES0_IPPE BIT(12) /*!< IP payload error */ +#define ENET_TDES0_FRMF BIT(13) /*!< frame flushed */ +#define ENET_TDES0_JT BIT(14) /*!< jabber timeout */ +#define ENET_TDES0_ES BIT(15) /*!< error summary */ +#define ENET_TDES0_IPHE BIT(16) /*!< IP header error */ +#define ENET_TDES0_TTMSS BIT(17) /*!< transmit timestamp status */ +#define ENET_TDES0_TCHM BIT(20) /*!< the second address chained mode */ +#define ENET_TDES0_TERM BIT(21) /*!< transmit end of ring mode*/ +#define ENET_TDES0_CM BITS(22,23) /*!< checksum mode */ +#define ENET_TDES0_TTSEN BIT(25) /*!< transmit timestamp function enable */ +#define ENET_TDES0_DPAD BIT(26) /*!< disable adding pad */ +#define ENET_TDES0_DCRC BIT(27) /*!< disable CRC */ +#define ENET_TDES0_FSG BIT(28) /*!< first segment */ +#define ENET_TDES0_LSG BIT(29) /*!< last segment */ +#define ENET_TDES0_INTC BIT(30) /*!< interrupt on completion */ +#define ENET_TDES0_DAV BIT(31) /*!< DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ +#define ENET_TDES1_TB1S BITS(0,12) /*!< transmit buffer 1 size */ +#define ENET_TDES1_TB2S BITS(16,28) /*!< transmit buffer 2 size */ + +/* ENET DMA Tx descriptor TDES2 */ +#define ENET_TDES2_TB1AP BITS(0,31) /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES3 */ +#define ENET_TDES3_TB2AP BITS(0,31) /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */ + +/* ENET DMA Rx descriptor RDES0 */ +#define ENET_RDES0_PCERR BIT(0) /*!< payload checksum error */ +#define ENET_RDES0_CERR BIT(1) /*!< CRC error */ +#define ENET_RDES0_DBERR BIT(2) /*!< dribble bit error */ +#define ENET_RDES0_RERR BIT(3) /*!< receive error */ +#define ENET_RDES0_RWDT BIT(4) /*!< receive watchdog timeout */ +#define ENET_RDES0_FRMT BIT(5) /*!< frame type */ +#define ENET_RDES0_LCO BIT(6) /*!< late collision */ +#define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ +#define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ +#define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ +#define ENET_RDES0_LERR BIT(12) /*!< length error */ +#define ENET_RDES0_SAFF BIT(13) /*!< SA filter fail */ +#define ENET_RDES0_DERR BIT(14) /*!< descriptor error */ +#define ENET_RDES0_ERRS BIT(15) /*!< error summary */ +#define ENET_RDES0_FRML BITS(16,29) /*!< frame length */ +#define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ +#define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ +#define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ +#define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ +#define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ +#define ENET_RDES1_RB2S BITS(16,28) /*!< receive buffer 2 size */ +#define ENET_RDES1_DINTC BIT(31) /*!< disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 */ +#define ENET_RDES2_RB1AP BITS(0,31) /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */ + +/* ENET DMA Rx descriptor RDES3 */ +#define ENET_RDES3_RB2AP BITS(0,31) /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */ + +/* constants definitions */ +/* define bit position and its register index offset */ +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* ENET clock range judgement */ +#define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) + +/* define MAC address configuration and reference address */ +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x40U) +#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) + +/* register offset */ +#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ + +#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ + +/* ENET status flag get */ +typedef enum +{ + /* ENET_MAC_WUM register */ + ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + /* ENET_MAC_FCTL register */ + ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ + /* ENET_MAC_INTF register */ + ENET_MAC_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_EB_DMA_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U), /*!< error during data transfer by RxDMA/TxDMA flag */ + ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U), /*!< error during write/read transfer flag */ + ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ + ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_flag_enum; + +/* ENET status flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_flag_clear_enum; + +/* ENET interrupt enable/disable */ +typedef enum +{ + /* ENET_MAC_INTMSK register */ + ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ + ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ + /* ENET_MSC_RINTMSK register */ + ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ + ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ + ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ + /* ENET_MSC_TINTMSK register */ + ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ + ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ + ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ + /* ENET_DMA_INTEN register */ + ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ + ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ + ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ + ENET_DMA_INT_TJTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U), /*!< transmit jabber timeout interrupt enable */ + ENET_DMA_INT_ROIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U), /*!< receive overflow interrupt enable */ + ENET_DMA_INT_TUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U), /*!< transmit underflow interrupt enable */ + ENET_DMA_INT_RIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U), /*!< receive interrupt enable */ + ENET_DMA_INT_RBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U), /*!< receive buffer unavailable interrupt enable */ + ENET_DMA_INT_RPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U), /*!< receive process stopped interrupt enable */ + ENET_DMA_INT_RWTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U), /*!< receive watchdog timeout interrupt enable */ + ENET_DMA_INT_ETIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U), /*!< early transmit interrupt enable */ + ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ + ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ + ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ +}enet_int_enum; + +/* ENET interrupt flag get */ +typedef enum +{ + /* ENET_MAC_INTF register */ + ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_INT_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_INT_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_INT_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_INT_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_INT_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_INT_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_INT_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_INT_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_INT_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_int_flag_enum; + +/* ENET interrupt flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_int_flag_clear_enum; + +/* current RX/TX descriptor/buffer/descriptor table address get */ +typedef enum +{ + ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ + ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ + ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ + ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ + ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ + ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ +}enet_desc_reg_enum; + +/* MAC statistics counter get */ +typedef enum +{ + ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ + ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ + ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ + ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ + ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ + ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ +}enet_msc_counter_enum; + +/* function option, used for ENET initialization */ +typedef enum +{ + FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ + DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ + DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ + DMA_ARBITRATION_OPTION = BIT(3), /*!< configure the DMA arbitration related parameters */ + STORE_OPTION = BIT(4), /*!< configure the store forward mode related parameters */ + DMA_OPTION = BIT(5), /*!< configure the DMA control related parameters */ + VLAN_OPTION = BIT(6), /*!< configure the VLAN tag related parameters */ + FLOWCTL_OPTION = BIT(7), /*!< configure the flow control related parameters */ + HASHH_OPTION = BIT(8), /*!< configure the hash list high 32-bit related parameters */ + HASHL_OPTION = BIT(9), /*!< configure the hash list low 32-bit related parameters */ + FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ + HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ + TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ + INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ +}enet_option_enum; + +/* phy mode and mac loopback configurations */ +typedef enum +{ + ENET_AUTO_NEGOTIATION = 0x01U, /*!< PHY auto negotiation */ + ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ + ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ + ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ +}enet_mediamode_enum; + +/* IP frame checksum function */ +typedef enum +{ + ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ + ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped */ +}enet_chksumconf_enum; + +/* received frame filter function */ +typedef enum +{ + ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ + ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ + ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ + ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ +}enet_frmrecept_enum; + +/* register group value get */ +typedef enum +{ + ALL_MAC_REG = 0, /*!< MAC register group */ + ALL_MSC_REG = 22, /*!< MSC register group */ + ALL_PTP_REG = 33, /*!< PTP register group */ + ALL_DMA_REG = 44, /*!< DMA register group */ +}enet_registers_type_enum; + +/* dma direction select */ +typedef enum +{ + ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ + ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ +}enet_dmadirection_enum; + +/* PHY operation direction select */ +typedef enum +{ + ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ + ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ +}enet_phydirection_enum; + +/* register operation direction select */ +typedef enum +{ + ENET_REG_READ, /*!< read register */ + ENET_REG_WRITE /*!< write register */ +}enet_regdirection_enum; + +/* ENET MAC addresses */ +typedef enum +{ + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ +}enet_macaddress_enum; + +/* descriptor information */ +typedef enum +{ + TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ + TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ + RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ + RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ + RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ + RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ +}enet_descstate_enum; + +/* structure for initialization of the ENET */ +typedef struct +{ + uint32_t option_enable; /*!< select which function to configure */ + uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ + uint32_t dma_maxburst; /*!< DMA max burst related parameters */ + uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ + uint32_t store_forward_mode; /*!< store forward mode related parameters */ + uint32_t dma_function; /*!< DMA control related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t flow_control; /*!< flow control related parameters */ + uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ + uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ + uint32_t framesfilter_mode; /*!< frame filter control related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t timer_config; /*!< frame timer related parameters */ + uint32_t interframegap; /*!< inter frame gap related parameters */ +}enet_initpara_struct; + +/* structure for ENET DMA descriptors */ +typedef struct +{ + uint32_t status; /*!< status */ + uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ + uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ + uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ +} enet_descriptors_struct; + +/* structure of PTP system time */ +typedef struct +{ + uint32_t second; /*!< second of system time */ + uint32_t nanosecond; /*!< nanosecond of system time */ + uint32_t sign; /*!< sign of system time */ +}enet_ptp_systime_struct; + +/* mac_cfg register value */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ + +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ +#define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ +#define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ +#define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ + +#define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ +#define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ + +#define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ +#define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ + +#define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ +#define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ + +#define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ +#define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ + +#define ENET_RECEIVEOWN_ENABLE ((uint32_t)0x00000000U) /*!< the MAC receives all packets that are given by the PHY while transmitting */ +#define ENET_RECEIVEOWN_DISABLE ENET_MAC_CFG_ROD /*!< the MAC disables the reception of frames in half-duplex mode */ + +#define ENET_LOOPBACKMODE_ENABLE ENET_MAC_CFG_LBM /*!< the MAC operates in loopback mode at the MII */ +#define ENET_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000U) /*!< the MAC operates in normal mode */ + +#define ENET_MODE_FULLDUPLEX ENET_MAC_CFG_DPM /*!< full-duplex mode enable */ +#define ENET_MODE_HALFDUPLEX ((uint32_t)0x00000000U) /*!< half-duplex mode enable */ + +#define ENET_CHECKSUMOFFLOAD_ENABLE ENET_MAC_CFG_IPFCO /*!< IP frame checksum offload function enabled for received IP frame */ +#define ENET_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000U) /*!< the checksum offload function in the receiver is disabled */ + +#define ENET_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000U) /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/ +#define ENET_RETRYTRANSMISSION_DISABLE ENET_MAC_CFG_RTD /*!< the MAC attempts only 1 transmission */ + +#define ENET_AUTO_PADCRC_DROP_ENABLE ENET_MAC_CFG_APCD /*!< the MAC strips the Pad/FCS field on received frames */ +#define ENET_AUTO_PADCRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< the MAC forwards all received frames without modify it */ +#define ENET_AUTO_PADCRC_DROP ENET_MAC_CFG_APCD /*!< the function of the MAC strips the Pad/FCS field on received frames */ + +#define ENET_DEFERRALCHECK_ENABLE ENET_MAC_CFG_DFC /*!< the deferral check function is enabled in the MAC */ +#define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ + +/* mac_frmf register value */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ +#define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ +#define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ + +#define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ +#define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ + +#define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ +#define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ +#define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ +#define ENET_SRC_FILTER ENET_MAC_FRMF_SAFLT /*!< filter source address function */ +#define ENET_SRC_FILTER_INVERSE ENET_MAC_FRMF_SAIFLT /*!< inverse source address filtering result function */ + +#define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ +#define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ + +#define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ + +#define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ +#define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ + +#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ +#define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ +#define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ +#define ENET_MULTICAST_FILTER_NONE ENET_MAC_FRMF_MFD /*!< all multicast frames are passed */ +#define ENET_MULTICAST_FILTER_PASS ENET_MAC_FRMF_MFD /*!< pass all multicast frames function */ +#define ENET_MULTICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HMF /*!< HASH multicast filter function */ +#define ENET_FILTER_MODE_EITHER ENET_MAC_FRMF_HPFLT /*!< HASH or perfect filter function */ + +#define ENET_UNICAST_FILTER_EITHER (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT) /*!< pass unicast frames that match either the perfect or the hash filtering */ +#define ENET_UNICAST_FILTER_HASH ENET_MAC_FRMF_HUF /*!< pass unicast frames that match the hash filtering */ +#define ENET_UNICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass unicast frames that match the perfect filtering */ +#define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ + +/* mac_phy_ctl register value */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ + +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ + +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ + +/* mac_phy_data register value */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ + +/* mac_fctl register value */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ + +#define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE ENET_MAC_FCTL_DZQP /*!< the automatic zero-quanta generation function */ + +#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ +#define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ + +#define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ +#define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ +#define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ + +#define ENET_TX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_TFCEN /*!< enable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< disable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL ENET_MAC_FCTL_TFCEN /*!< the flow control operation in the MAC */ + +#define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ +/* mac_vlt register value */ +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + +#define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ +#define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ + +/* mac_wum register value */ +#define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ +#define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ +#define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + +/* mac_addr0h register value */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ + +/* mac_addrxh register value, x = 1,2,3 */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ + +#define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ +#define ENET_ADDRESS_MASK_BYTE2 BIT(26) /*!< low register bits [23:16] */ +#define ENET_ADDRESS_MASK_BYTE3 BIT(27) /*!< low register bits [31:24] */ +#define ENET_ADDRESS_MASK_BYTE4 BIT(28) /*!< high register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ + +#define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + +/* mac_fcth register value */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ +#define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ +#define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ +#define ENET_ACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFA(3) /*!< threshold level is 1024 bytes */ +#define ENET_ACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFA(4) /*!< threshold level is 1280 bytes */ +#define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ +#define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ + +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4))<<8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ +#define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ +#define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFD(3) /*!< threshold level is 1024 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFD(4) /*!< threshold level is 1280 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFD(5) /*!< threshold level is 1536 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFD(6) /*!< threshold level is 1792 bytes */ + +/* msc_ctl register value */ +#define ENET_MSC_COUNTER_STOP_ROLLOVER ENET_MSC_CTL_CTSR /*!< counter stop rollover */ +#define ENET_MSC_RESET_ON_READ ENET_MSC_CTL_RTOR /*!< reset on read */ +#define ENET_MSC_COUNTERS_FREEZE ENET_MSC_CTL_MCFZ /*!< MSC counter freeze */ + +/* ptp_tsctl register value */ +#define ENET_RXTX_TIMESTAMP ENET_PTP_TSCTL_TMSEN /*!< enable timestamp function for transmit and receive frames */ +#define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ + +/* ptp_ssinc register value */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ + +/* ptp_tsl register value */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ + +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ + +/* ptp_tsul register value */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ + +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ + +/* dma_bctl register value */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ + +/* dma_stat register value */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ +#define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ + +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ +#define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ + +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ + +/* dma_ctl register value */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ + +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES DMA_CTL_TTHC(3) /*!< threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES DMA_CTL_TTHC(4) /*!< threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES DMA_CTL_TTHC(5) /*!< threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES DMA_CTL_TTHC(6) /*!< threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ + +#define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ + +#define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ + +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ + +#define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ + +#define ENET_FORWARD_ERRFRAMES_ENABLE (ENET_DMA_CTL_FERF<<2) /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF<<2) /*!< the function that all frame received with error except runt error are forwarded to memory */ + +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF<<2) /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF<<2) /*!< the function that forwarding undersized good frames */ + +#define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ + +/* dma_mfbocnt register value */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ + +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ + +/* dma tx descriptor tdes0 register value */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ + +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ + +/* dma tx descriptor tdes1 register value */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ + +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ + +/* dma rx descriptor rdes0 register value */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ + +/* dma rx descriptor rdes1 register value */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ + +#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ + +#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ + +/* dma rx descriptor rdes4 register value */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ + +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ + +/* ENET register mask value */ +#define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ +#define MAC_FCTL_MASK ((uint32_t)0x0000FF41U) /*!< ENET_MAC_FCTL register mask */ +#define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ +#define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ + +#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ + +typedef enum{ + ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ +}enet_ptp_function_enum; + + +/* ENET remote wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ + +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ + +/* ENET delay timeout */ +#define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ +#define ENET_RESET_TO ((uint32_t)0x000004FFU) /*!< ENET reset timeout */ + +/* function declarations */ +/* main function */ +/* deinitialize the ENET, and reset structure parameters for ENET initialization */ +void enet_deinit(void); +/* configure the parameters which are usually less cared for initialization */ +void enet_initpara_config(enet_option_enum option, uint32_t para); +/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept); +/* reset all core internal registers located in CLK_TX and CLK_RX */ +ErrStatus enet_software_reset(void); +/* check receive frame valid and return frame size */ +uint32_t enet_rxframe_size_get(void); +/* initialize the dma tx/rx descriptors's parameters in chain mode */ +void enet_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma tx/rx descriptors's parameters in ring mode */ +void enet_descriptors_ring_init(enet_dmadirection_enum direction); +/* handle current received frame data to application buffer */ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize); +/* handle current received frame but without data copy to application buffer */ +#define ENET_NOCOPY_FRAME_RECEIVE() enet_frame_receive(NULL, 0U) +/* handle application buffer data to transmit it */ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); +/* handle current transmit frame but without data copy from application buffer */ +#define ENET_NOCOPY_FRAME_TRANSMIT(len) enet_frame_transmit(NULL, (len)) +/* configure the transmit IP frame checksum offload calculation and insertion */ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); +/* ENET Tx and Rx function enable (include MAC and DMA module) */ +void enet_enable(void); +/* ENET Tx and Rx function disable (include MAC and DMA module) */ +void enet_disable(void); +/* configure MAC address */ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); +/* get MAC address */ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]); + +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + +/* MAC function */ +/* ENET Tx function enable (include MAC and DMA module) */ +void enet_tx_enable(void); +/* ENET Tx function disable (include MAC and DMA module) */ +void enet_tx_disable(void); +/* ENET Rx function enable (include MAC and DMA module) */ +void enet_rx_enable(void); +/* ENET Rx function disable (include MAC and DMA module) */ +void enet_rx_disable(void); +/* put registers value into the application buffer */ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num); +/* get the enet debug status from the debug register */ +uint32_t enet_debug_status_get(uint32_t mac_debug); +/* enable the MAC address filter */ +void enet_address_filter_enable(enet_macaddress_enum mac_addr); +/* disable the MAC address filter */ +void enet_address_filter_disable(enet_macaddress_enum mac_addr); +/* configure the MAC address filter */ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type); +/* PHY interface configuration (configure SMI clock and reset PHY chip) */ +ErrStatus enet_phy_config(void); +/* write to/read from a PHY register */ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue); +/* enable the loopback function of phy chip */ +ErrStatus enet_phyloopback_enable(void); +/* disable the loopback function of phy chip */ +ErrStatus enet_phyloopback_disable(void); +/* enable ENET forward feature */ +void enet_forward_feature_enable(uint32_t feature); +/* disable ENET forward feature */ +void enet_forward_feature_disable(uint32_t feature); +/* enable ENET fliter feature */ +void enet_fliter_feature_enable(uint32_t feature); +/* disable ENET fliter feature */ +void enet_fliter_feature_disable(uint32_t feature); + +/* flow control function */ +/* generate the pause frame, ENET will send pause frame after enable transmit flow control */ +ErrStatus enet_pauseframe_generate(void); +/* configure the pause frame detect type */ +void enet_pauseframe_detect_config(uint32_t detect); +/* configure the pause frame parameters */ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold); +/* configure the threshold of the flow control(deactive and active threshold) */ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active); +/* enable ENET flow control feature */ +void enet_flowcontrol_feature_enable(uint32_t feature); +/* disable ENET flow control feature */ +void enet_flowcontrol_feature_disable(uint32_t feature); + +/* DMA function */ +/* get the dma transmit/receive process state */ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +/* poll the dma transmission/reception enable */ +void enet_dmaprocess_resume(enet_dmadirection_enum direction); +/* check and recover the Rx process */ +void enet_rxprocess_check_recovery(void); +/* flush the ENET transmit fifo, and wait until the flush operation completes */ +ErrStatus enet_txfifo_flush(void); +/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get); +/* get the Tx or Rx descriptor information */ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get); +/* get the number of missed frames during receiving */ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop); + +/* descriptor function */ +/* get the bit flag of ENET dma descriptor */ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag); +/* set the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); +/* clear the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will set */ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will not set */ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc); +/* drop current receive frame */ +void enet_rxframe_drop(void); +/* enable DMA feature */ +void enet_dma_feature_enable(uint32_t feature); +/* disable DMA feature */ +void enet_dma_feature_disable(uint32_t feature); + +/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr) enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr) enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr)) + +/* WUM function */ +/* wakeup frame filter register pointer reset */ +void enet_wum_filter_register_pointer_reset(void); +/* set the remote wakeup frame registers */ +void enet_wum_filter_config(uint32_t pdata[]); +/* enable wakeup management features */ +void enet_wum_feature_enable(uint32_t feature); +/* disable wakeup management features */ +void enet_wum_feature_disable(uint32_t feature); + +/* MSC function */ +/* reset the MAC statistics counters */ +void enet_msc_counters_reset(void); +/* enable the MAC statistics counter features */ +void enet_msc_feature_enable(uint32_t feature); +/* disable the MAC statistics counter features */ +void enet_msc_feature_disable(uint32_t feature); +/* get MAC statistics counter */ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); + +/* PTP function */ +/* change subsecond to nanosecond */ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond); +/* change nanosecond to subsecond */ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond); +/* enable the PTP features */ +void enet_ptp_feature_enable(uint32_t feature); +/* disable the PTP features */ +void enet_ptp_feature_disable(uint32_t feature); +/* configure the PTP timestamp function */ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func); +/* configure the PTP system time subsecond increment value */ +void enet_ptp_subsecond_increment_config(uint32_t subsecond); +/* adjusting the PTP clock frequency only in fine update mode */ +void enet_ptp_timestamp_addend_config(uint32_t add); +/* initializing or adding/subtracting to second of the PTP system time */ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond); +/* configure the PTP expected target time */ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond); +/* get the PTP current system time */ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct); +/* configure and start PTP timestamp counter */ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg); +/* adjust frequency in fine method by configure addend register */ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); +/* update system time in coarse method */ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); +/* set system time in fine method */ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +/* get the ptp flag status */ +FlagStatus enet_ptp_flag_get(uint32_t flag); + +/* internal function */ +/* reset the ENET initpara struct, call it before using enet_initpara_config() */ +void enet_initpara_reset(void); +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + +#endif /* GD32F20X_ENET_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h new file mode 100644 index 0000000000..ef2cc2f1f1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h @@ -0,0 +1,920 @@ +/*! + \file gd32f20x_exmc.h + \brief definitions for the EXMC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_EXMC_H +#define GD32F20X_EXMC_H + +#include "gd32f20x.h" + +/* EXMC definitions */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ +#define EXMC_NOR_PSRAM (EXMC_BASE - 0x40000000) /*!< EXMC NOR/PSRAM base address */ +#define EXMC_NAND (EXMC_BASE - 0x30000000) /*!< EXMC NAND base address */ +#define EXMC_PCCARD (EXMC_BASE - 0x10000000) /*!< EXMC PC card base address */ +#define EXMC_SDRAM (EXMC_BASE + 0x20000000) /*!< EXMC SDRAM base address */ + +/* registers definitions */ +/* NOR/PSRAM */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +/* NAND/PC card */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register */ + +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ + +/* SDRAM */ +#define EXMC_SDCTL0 REG32(EXMC + 0x140U) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG0 REG32(EXMC + 0x148U) /*!< EXMC SDRAM timing configuration register register */ + +#define EXMC_SDCTL1 REG32(EXMC + 0x144U) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG1 REG32(EXMC + 0x14CU) /*!< EXMC SDRAM timing configuration register register */ + +#define EXMC_SDCMD REG32(EXMC + 0x150U) /*!< EXMC SDRAM command register */ +#define EXMC_SDARI REG32(EXMC + 0x154U) /*!< EXMC SDRAM auto-refresh interval register */ +#define EXMC_SDSTAT REG32(EXMC + 0x158U) /*!< EXMC SDRAM status register */ +#define EXMC_SDRSCTL REG32(EXMC + 0x180U) /*!< EXMC SDRAM read sample control register */ + +/* SQPI PSRAM */ +#define EXMC_SINIT REG32(EXMC + 0x310U) /*!< EXMC SPI initialization register */ +#define EXMC_SRCMD REG32(EXMC + 0x320U) /*!< EXMC SPI read command register */ +#define EXMC_SWCMD REG32(EXMC + 0x330U) /*!< EXMC SPI write command register */ +#define EXMC_SIDL REG32(EXMC + 0x340U) /*!< EXMC SPI ID low register */ +#define EXMC_SIDH REG32(EXMC + 0x350U) /*!< EXMC SPI ID high register */ + +/* bits definitions */ +/* NOR/PSRAM */ +/* EXMC_SNCTLx,x=0..3 */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write */ + +/* EXMC_SNTCFGx,x=0..3 */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_SNWTCFGx,x=0..3 */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNWTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNWTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* NAND/PC card */ +/* EXMC_NPCTLx,x=1..3 */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ + +/* EXMC_NPINTENx,x=1..3 */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ + +/* EXMC_NPCTCFGx,x=1..3 */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ + +/* EXMC_NPATCFGx,x=1..3 */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ + +/* EXMC_PIOTCFG3 */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ + +/* EXMC_NECCx,x=1..2 */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ + +/* SDRAM */ +/* EXMC_SDCTLx,x=0..1 */ +#define EXMC_SDCTL_CAW BITS(0,1) /*!< column address bit width */ +#define EXMC_SDCTL_RAW BITS(2,3) /*!< row address bit width */ +#define EXMC_SDCTL_SDW BITS(4,5) /*!< SDRAM data bus width */ +#define EXMC_SDCTL_NBK BIT(6) /*!< number of banks */ +#define EXMC_SDCTL_CL BIT(7,8) /*!< CAS Latency */ +#define EXMC_SDCTL_WPEN BIT(9) /*!< write protection enable */ +#define EXMC_SDCTL_SDCLK BITS(10,11) /*!< SDRAM clock configuration */ +#define EXMC_SDCTL_BRSTRD BIT(12) /*!< burst read */ +#define EXMC_SDCTL_PIPED BITS(13,14) /*!< pipeline delay */ + +/* EXMC_SDTCFGx,x=0..1 */ +#define EXMC_SDTCFG_LMRD BITS(0,3) /*!< load mode register delay */ +#define EXMC_SDTCFG_XSRD BITS(4,7) /*!< exit self-refresh delay */ +#define EXMC_SDTCFG_RASD BITS(8,11) /*!< row address select delay */ +#define EXMC_SDTCFG_ARFD BITS(12,15) /*!< auto refresh delay */ +#define EXMC_SDTCFG_WRD BITS(16,19) /*!< write recovery delay */ +#define EXMC_SDTCFG_RPD BITS(20,23) /*!< row precharge delay */ +#define EXMC_SDTCFG_RCD BITS(24,27) /*!< row to column delay */ + +/* EXMC_SDCMD */ +#define EXMC_SDCMD_CMD BITS(0,2) /*!< command */ +#define EXMC_SDCMD_DS1 BIT(3) /*!< device select 1 */ +#define EXMC_SDCMD_DS0 BIT(4) /*!< device select 0 */ +#define EXMC_SDCMD_NARF BITS(5,8) /*!< number of successive auto-refresh */ +#define EXMC_SDCMD_MRC BITS(9,21) /*!< mode register content */ + +/* EXMC_SDARI */ +#define EXMC_SDARI_REC BIT(0) /*!< refresh error flag clear */ +#define EXMC_SDARI_ARINTV BITS(1,13) /*!< auto-refresh interval */ +#define EXMC_SDARI_REIE BIT(14) /*!< interrupt refresh error enable */ + +/* EXMC_SDSTAT */ +#define EXMC_SDSDAT_REIF BIT(0) /*!< refresh error interrupt flag */ +#define EXMC_SDSDAT_STA0 BITS(1,2) /*!< device 0 status */ +#define EXMC_SDSDAT_STA1 BITS(3,4) /*!< device 1 status */ +#define EXMC_SDSDAT_NRDY BIT(5) /*!< not ready status */ + +/* EXMC_SDRSCTL */ +#define EXMC_SDRSCTL_RSEN BIT(0) /*!< read sample enable */ +#define EXMC_SDRSCTL_SSCR BIT(1) /*!< select sample cycle of read data */ +#define EXMC_SDRSCTL_SDSC BITS(4,7) /*!< select the delayed sample clock of read data */ + +/* SQPI PSRAM */ +/* EXMC_SINIT */ +#define EXMC_SINIT_CMDBIT BITS(16,17) /*!< bit number of SPI PSRAM command phase */ +#define EXMC_SINIT_ARDBIT BITS(24,28) /*!< bit number of SPI PSRAM address phase */ +#define EXMC_SINIT_IDL BITS(29,30) /*!< SPI PSRAM ID length */ +#define EXMC_SINIT_POL BIT(31) /*!< read data sample polarity */ + +/* EXMC_SRCMD */ +#define EXMC_SRCMD_RCMD BITS(0,15) /*!< SPI read command for AHB read transfer */ +#define EXMC_SRCMD_RWAITCYCLE BITS(16,19) /*!< SPI read wait cycle number after address phase */ +#define EXMC_SRCMD_RMODE BITS(20,21) /*!< SPI PSRAM read command mode */ +#define EXMC_SRCMD_RDID BIT(31) /*!< send SPI read ID command */ + +/* EXMC_SWCMD */ +#define EXMC_SWCMD_WCMD BITS(0,15) /*!< SPI write command for AHB write transfer */ +#define EXMC_SWCMD_WWAITCYCLE BITS(16,19) /*!< SPI write wait cycle number after address phase */ +#define EXMC_SWCMD_WMODE BITS(20,21) /*!< SPI PSRAM write command mode */ +#define EXMC_SWCMD_SC BIT(31) /*!< send SPI special command */ + +/* EXMC_SIDL */ +#define EXMC_SIDL_SIDL BITS(0,31) /*!< ID low data saved for SPI read ID command */ + +/* EXMC_SIDH */ +#define EXMC_SIDL_SIDH BITS(0,31) /*!< ID high Data saved for SPI read ID command */ + +/* constants definitions */ +/* EXMC NOR/SRAM timing initialize structure */ +typedef struct +{ + uint32_t asyn_access_mode; /*!< asynchronous access mode */ + + uint32_t syn_data_latency; /*!< configure the data latency */ + /*!< the range is EXMC_DATALAT_2_CLK to EXMC_DATALAT_17_CLK */ + + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ + /*!< the range is EXMC_SYN_CLOCK_RATIO_2_CLK to EXMC_SYN_CLOCK_RATIO_16_CLK */ + + uint32_t bus_latency; /*!< configure the bus latency */ + /*!< the range is 1 to 16 HCLK */ + + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + /*!< the range is 2 to 256 HCLK */ + + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ + /*!< the range is 2 to 16 HCLK */ + + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + /*!< the range is 1 to 16 HCLK */ +}exmc_norsram_timing_parameter_struct; + +/* EXMC NOR/SRAM initialize structure */ +typedef struct +{ + uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ + /*!< norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 */ + + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ + /*!< write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE */ + + uint32_t extended_mode; /*!< enable or disable the extended mode */ + /*!< extended_mode: ENABLE or DISABLE */ + + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ + /*!< asyn_wait: ENABLE or DISABLE */ + + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ + /*!< nwait_signal: ENABLE or DISABLE */ + + uint32_t memory_write; /*!< enable or disable the write operation */ + /*!< memory_write: ENABLE or DISABLE */ + + uint32_t nwait_config; /*!< NWAIT signal configuration */ + /*!< nwait_config: EXMC_NWAIT_CONFIG_BEFORE or EXMC_NWAIT_CONFIG_DURING */ + + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ + /*!< wrap_burst_mode: ENABLE or DISABLE */ + + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ + /*!< nwait_polarity: EXMC_NWAIT_POLARITY_LOW or EXMC_NWAIT_POLARITY_HIGH */ + + uint32_t burst_mode; /*!< enable or disable the burst mode */ + /*!< burst_mode: ENABLE or DISABLE */ + + uint32_t databus_width; /*!< specifies the databus width of external memory */ + /*!< databus_width: EXMC_NOR_DATABUS_WIDTH_8B or EXMC_NOR_DATABUS_WIDTH_16B */ + + uint32_t memory_type; /*!< specifies the type of external memory */ + /*!< memory_type: EXMC_MEMORY_TYPE_SRAM / EXMC_MEMORY_TYPE_PSRAM / EXMC_MEMORY_TYPE_NOR */ + + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ + /*!< address_data_mux: ENABLE or DISABLE */ + + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extendedmode is not used or the timing + parameters for read if the extendedmode is used. */ + + exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extendedmode is used. */ +}exmc_norsram_parameter_struct; + +/* EXMC NAND/PC card timing initialize struct */ +typedef struct +{ + uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ + /*!< the range is 1 to 256 HCLK */ + + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ + /*!< the range is 1 to 255 HCLK */ + + uint32_t waittime; /*!< configure the minimum wait time */ + /*!< the range is 2 to 256 HCLK (+NWAIT active cycles) */ + + uint32_t setuptime; /*!< configure the address setup time */ + /*!< the range is 1 to 256 HCLK */ +}exmc_nand_pccard_timing_parameter_struct; + +/* EXMC NAND initialize structure */ +typedef struct +{ + uint32_t nand_bank; /*!< select the bank of NAND */ + /*!< nand_bank: EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + + uint32_t ecc_size; /*!< the page size for the ECC calculation */ + /*!< ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 */ + + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ + /*!< ecc_logic: ENABLE or DISABLE */ + + uint32_t databus_width; /*!< the NAND flash databus width */ + /*!< databus_width: EXMC_NAND_DATABUS_WIDTH_8B or EXMC_NAND_DATABUS_WIDTH_16B */ + + uint32_t wait_feature; /*!< enables or disables the wait feature */ + /*!< wait_feature: ENABLE or DISABLE */ + + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ + + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ +}exmc_nand_parameter_struct; + +/* EXMC PC card initialize structure */ +typedef struct +{ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t wait_feature; /*!< enables or disables the Wait feature */ + /*!< wait_feature: ENABLE or DISABLE */ + + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ + + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ + + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO Space */ +}exmc_pccard_parameter_struct;; + +/* EXMC SDRAM timing initialize structure */ +typedef struct +{ + uint32_t row_to_column_delay; /*!< configure the row to column delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t row_precharge_delay; /*!< configure the row precharge delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t write_recovery_delay; /*!< configure the write recovery delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t auto_refresh_delay; /*!< configure the auto refresh delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t row_address_select_delay; /*!< configure the row address select delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t exit_selfrefresh_delay; /*!< configure the exit self-refresh delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t load_mode_register_delay; /*!< configure the load mode register delay */ + /*!< the range is 1 to 16 cycles */ +}exmc_sdram_timing_parameter_struct; + +/* EXMC SDRAM initialize structure */ +typedef struct +{ + uint32_t sdram_device; /*!< device of SDRAM */ + /*!< sdram_device: EXMC_SDRAM_DEVICE0 or EXMC_SDRAM_DEVICE1 */ + + uint32_t pipeline_read_delay; /*!< the delay for reading data after CAS latency in HCLK clock cycles */ + /*!< pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK, x=0..2 */ + + uint32_t brust_read_switch; /*!< enable or disable the burst read */ + /*!< brust_read_switch: ENABLE or DISABLE */ + + uint32_t sdclock_config; /*!< the SDCLK memory clock for both SDRAM banks */ + /*!< sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK */ + + uint32_t write_protection; /*!< enable or disable SDRAM bank write protection function */ + /*!< write_protection: ENABLE or DISABLE */ + + uint32_t cas_latency; /*!< configure the SDRAM CAS latency */ + /*!< cas_latency: EXMC_CAS_LATENCY_x_SDCLK, x=1..3 */ + + uint32_t internal_bank_number; /*!< the number internal banks */ + /*!< internal_bank_number: EXMC_SDRAM_2_INTER_BANK or EXMC_SDRAM_4_INTER_BANK */ + + uint32_t data_width; /*!< the databus width of SDRAM memory */ + /*!< data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B */ + + uint32_t row_address_width; /*!< the bit width of a row address */ + /*!< row_address_width: EXMC_SDRAM_ROW_ADDRESS_x, x=11..13 */ + + uint32_t column_address_width; /*!< the bit width of a column address */ + /*!< column_address_width: EXMC_SDRAM_COW_ADDRESS_x, x=8..11 */ + + exmc_sdram_timing_parameter_struct* timing; /*!< the timing parameters for write and read SDRAM */ +}exmc_sdram_parameter_struct; + +/* EXMC SDRAM command initialize structure */ +typedef struct +{ + uint32_t mode_register_content; /*!< the SDRAM mode register content */ + /*!< mode_register_content: */ + + uint32_t auto_refresh_number; /*!< the number of successive auto-refresh cycles will be send when CMD = 011 */ + /*!< auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 */ + + uint32_t bank_select; /*!< the bank which command will be sent to */ + /*!< bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT */ + + uint32_t command; /*!< the commands that will be sent to SDRAM */ + /*!< command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY */ +}exmc_sdram_command_parameter_struct; + +/* EXMC SQPISRAM initialize structure */ +typedef struct{ + uint32_t sample_polarity; /*!< read data sample polarity */ + /*!< sample_polarity: EXMC_SDRAM_SAMPLE_RISING_EDGE,EXMC_SDRAM_SAMPLE_FALLING_EDGE */ + + uint32_t id_length; /*!< SPI PSRAM ID length */ + /*!< id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 */ + + uint32_t address_bits; /*!< bit number of SPI PSRAM address phase */ + /*!< address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 */ + + uint32_t command_bits; /*!< bit number of SPI PSRAM command phase */ + /*!< command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 */ +}exmc_sqpipsram_parameter_struct; + +/* EXMC NOR/SRAM bank region definition */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ + +/* EXMC NAND/PC card bank definition */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ + +/* EXMC SDRAM bank definition */ +#define EXMC_SDRAM_DEVICE0 ((uint32_t)0x00000004U) /*!< SDRAM device0 */ +#define EXMC_SDRAM_DEVICE1 ((uint32_t)0x00000005U) /*!< SDRAM device1 */ + +/* EXMC_register address */ +#define EXMC_SNCTL(bank) REG32(EXMC + 0x08U*((uint32_t)(bank))) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG(bank) REG32(EXMC + 0x04U + 0x08U*(bank)) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG(bank) REG32(EXMC + 0x104U + 0x08U*(bank)) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U*(bank)) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U*(bank)) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U*(bank)) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U*(bank)) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U*(bank)) /*!< EXMC NAND ECC register */ + +#define EXMC_SDCTL(bank) REG32(EXMC + 0x140U + 0x4U*((bank) - 0x4U)) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG(bank) REG32(EXMC + 0x148U + 0x4U*((bank) - 0x4U)) /*!< EXMC SDRAM timing configuration register */ + +/* NOR/PSRAM */ +/* NOR bank memory data bus width */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width 16 bits */ + +/* NOR bank memory type */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ + +/* asynchronous access mode */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ + +/* data latency for NOR flash */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency 17 EXMC_CLK */ + +/* synchronous clock divide ratio */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ +/* EXMC NOR/SRAM write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE EXMC_SNCTL_SYNCWR /*!< synchronous write mode */ + +/* EXMC NWAIT signal configuration */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING EXMC_SNCTL_NRWTCFG /*!< NWAIT signal is active during wait state */ + +/* EXMC NWAIT signal polarity configuration */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH EXMC_SNCTL_NRWTPOL /*!< high level is active of NWAIT */ + +/* NAND/PC card */ +/* ECC size */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* 8192 bytes */ + +/* ALE to RE delay */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ + +/* CLE to RE delay */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ + +/* NAND bank memory data bus width */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width 16 bits */ + +/* SDRAM */ +/* SDRAM pipeline delay */ +#define SDCTL_PIPED(regval) (BITS(13,14) & ((uint32_t)(regval) << 13)) +#define EXMC_PIPELINE_DELAY_0_HCLK SDCTL_PIPED(0) /*!< 0 HCLK clock cycle delay */ +#define EXMC_PIPELINE_DELAY_1_HCLK SDCTL_PIPED(1) /*!< 1 HCLK clock cycle delay */ +#define EXMC_PIPELINE_DELAY_2_HCLK SDCTL_PIPED(2) /*!< 2 HCLK clock cycle delay */ + +/* SDRAM clock configuration */ +#define SDCTL_SDCLK(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) +#define EXMC_SDCLK_DISABLE SDCTL_SDCLK(0) /*!< SDCLK memory clock disabled */ +#define EXMC_SDCLK_PERIODS_2_HCLK SDCTL_SDCLK(2) /*!< SDCLK memory period = 2*HCLK */ +#define EXMC_SDCLK_PERIODS_3_HCLK SDCTL_SDCLK(3) /*!< SDCLK memory period = 3*HCLK */ + +/* CAS latency */ +#define SDCTL_CL(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) +#define EXMC_CAS_LATENCY_1_SDCLK SDCTL_CL(1) /*!< CAS latency is 1 memory clock cycle */ +#define EXMC_CAS_LATENCY_2_SDCLK SDCTL_CL(2) /*!< CAS latency is 2 memory clock cycle */ +#define EXMC_CAS_LATENCY_3_SDCLK SDCTL_CL(3) /*!< CAS latency is 3 memory clock cycle */ + +/* SDRAM data bus width */ +#define SDCTL_SDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_SDRAM_DATABUS_WIDTH_8B SDCTL_SDW(0) /*!< SDRAM data width 8 bits */ +#define EXMC_SDRAM_DATABUS_WIDTH_16B SDCTL_SDW(1) /*!< SDRAM data width 16 bits */ +#define EXMC_SDRAM_DATABUS_WIDTH_32B SDCTL_SDW(2) /*!< SDRAM data width 32 bits */ + +/* SDRAM row address bit width */ +#define SDCTL_RAW(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_SDRAM_ROW_ADDRESS_11 SDCTL_RAW(0) /*!< row address bit width is 11 bits */ +#define EXMC_SDRAM_ROW_ADDRESS_12 SDCTL_RAW(1) /*!< row address bit width is 12 bits */ +#define EXMC_SDRAM_ROW_ADDRESS_13 SDCTL_RAW(2) /*!< row address bit width is 13 bits */ + +/* SDRAM column address bit width */ +#define SDCTL_CAW(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define EXMC_SDRAM_COW_ADDRESS_8 SDCTL_CAW(0) /*!< column address bit width is 8 bits */ +#define EXMC_SDRAM_COW_ADDRESS_9 SDCTL_CAW(1) /*!< column address bit width is 9 bits */ +#define EXMC_SDRAM_COW_ADDRESS_10 SDCTL_CAW(2) /*!< column address bit width is 10 bits */ +#define EXMC_SDRAM_COW_ADDRESS_11 SDCTL_CAW(3) /*!< column address bit width is 11 bits */ + +/* SDRAM number of successive auto-refresh */ +#define SDCMD_NARF(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) +#define EXMC_SDRAM_AUTO_REFLESH_1_SDCLK SDCMD_NARF(0) /*!< 1 auto-refresh cycle */ +#define EXMC_SDRAM_AUTO_REFLESH_2_SDCLK SDCMD_NARF(1) /*!< 2 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_3_SDCLK SDCMD_NARF(2) /*!< 3 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_4_SDCLK SDCMD_NARF(3) /*!< 4 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_5_SDCLK SDCMD_NARF(4) /*!< 5 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_6_SDCLK SDCMD_NARF(5) /*!< 6 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_7_SDCLK SDCMD_NARF(6) /*!< 7 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_8_SDCLK SDCMD_NARF(7) /*!< 8 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_9_SDCLK SDCMD_NARF(8) /*!< 9 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_10_SDCLK SDCMD_NARF(9) /*!< 10 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_11_SDCLK SDCMD_NARF(10) /*!< 11 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_12_SDCLK SDCMD_NARF(11) /*!< 12 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_13_SDCLK SDCMD_NARF(12) /*!< 13 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_14_SDCLK SDCMD_NARF(13) /*!< 14 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_15_SDCLK SDCMD_NARF(14) /*!< 15 auto-refresh cycles */ + +/* SDRAM command select */ +#define SDCMD_CMD(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define EXMC_SDRAM_NORMAL_OPERATION SDCMD_CMD(0) /*!< normal operation command */ +#define EXMC_SDRAM_CLOCK_ENABLE SDCMD_CMD(1) /*!< clock enable command */ +#define EXMC_SDRAM_PRECHARGE_ALL SDCMD_CMD(2) /*!< precharge all command */ +#define EXMC_SDRAM_AUTO_REFRESH SDCMD_CMD(3) /*!< auto-refresh command */ +#define EXMC_SDRAM_LOAD_MODE_REGISTER SDCMD_CMD(4) /*!< load mode register command */ +#define EXMC_SDRAM_SELF_REFRESH SDCMD_CMD(5) /*!< self-refresh command */ +#define EXMC_SDRAM_POWERDOWN_ENTRY SDCMD_CMD(6) /*!< power-down entry command */ + +/* SDRAM the delayed sample clock of read data */ +#define SDRSCTL_SDSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define EXMC_SDRAM_0_DELAY_CELL SDRSCTL_SDSC(0) /*!< select the clock after 0 delay cell */ +#define EXMC_SDRAM_1_DELAY_CELL SDRSCTL_SDSC(1) /*!< select the clock after 1 delay cell */ +#define EXMC_SDRAM_2_DELAY_CELL SDRSCTL_SDSC(2) /*!< select the clock after 2 delay cell */ +#define EXMC_SDRAM_3_DELAY_CELL SDRSCTL_SDSC(3) /*!< select the clock after 3 delay cell */ +#define EXMC_SDRAM_4_DELAY_CELL SDRSCTL_SDSC(4) /*!< select the clock after 4 delay cell */ +#define EXMC_SDRAM_5_DELAY_CELL SDRSCTL_SDSC(5) /*!< select the clock after 5 delay cell */ +#define EXMC_SDRAM_6_DELAY_CELL SDRSCTL_SDSC(6) /*!< select the clock after 6 delay cell */ +#define EXMC_SDRAM_7_DELAY_CELL SDRSCTL_SDSC(7) /*!< select the clock after 7 delay cell */ +#define EXMC_SDRAM_8_DELAY_CELL SDRSCTL_SDSC(8) /*!< select the clock after 8 delay cell */ +#define EXMC_SDRAM_9_DELAY_CELL SDRSCTL_SDSC(9) /*!< select the clock after 9 delay cell */ +#define EXMC_SDRAM_10_DELAY_CELL SDRSCTL_SDSC(10) /*!< select the clock after 10 delay cell */ +#define EXMC_SDRAM_11_DELAY_CELL SDRSCTL_SDSC(11) /*!< select the clock after 11 delay cell */ +#define EXMC_SDRAM_12_DELAY_CELL SDRSCTL_SDSC(12) /*!< select the clock after 12 delay cell */ +#define EXMC_SDRAM_13_DELAY_CELL SDRSCTL_SDSC(13) /*!< select the clock after 13 delay cell */ +#define EXMC_SDRAM_14_DELAY_CELL SDRSCTL_SDSC(14) /*!< select the clock after 14 delay cell */ +#define EXMC_SDRAM_15_DELAY_CELL SDRSCTL_SDSC(15) /*!< select the clock after 15 delay cell */ + + /* EXMC SDRAM internal banks */ +#define EXMC_SDRAM_2_INTER_BANK ((uint32_t)0x00000000U) /*!< 2 internal banks */ +#define EXMC_SDRAM_4_INTER_BANK EXMC_SDCTL_NBK /*!< 4 internal banks */ + +/* SDRAM device0 select */ +#define EXMC_SDRAM_DEVICE0_SELECT EXMC_SDCMD_DS0 /*!< SDRAM Device0 is selected */ + +/* SDRAM device1 select */ +#define EXMC_SDRAM_DEVICE1_SELECT EXMC_SDCMD_DS1 /*!< SDRAM Device1 is selected */ + +/* SDRAM device0 and device1 select */ +#define EXMC_SDRAM_DEVICE0_1_SELECT (EXMC_SDCMD_DS0 | EXMC_SDCMD_DS1) /*!< SDRAM Device1 is selected */ + +/* SDRAM device status */ +#define EXMC_SDRAM_DEVICE_NORMAL ((uint32_t)0x00000000U) /*!< normal status */ +#define EXMC_SDRAM_DEVICE_SELF_REFRESH ((uint32_t)0x00000001U) /*!< self refresh status */ +#define EXMC_SDRAM_DEVICE_POWER_DOWN ((uint32_t)0x00000002U) /*!< power down status */ + +/* sample cycle of read data */ +#define EXMC_SDRAM_READSAMPLE_0_EXTRAHCLK ((uint32_t)0x00000000U) /*!< add 0 extra HCLK cycle to the read data sample clock besides the delay chain */ +#define EXMC_SDRAM_READSAMPLE_1_EXTRAHCLK EXMC_SDRSCTL_SSCR /*!< add 1 extra HCLK cycle to the read data sample clock besides the delay chain */ + +/* SQPI PSRAM */ +/* SPI PSRAM ID length */ +#define SINIT_IDL(regval) (BITS(29,30) & ((uint32_t)(regval) << 29)) +#define EXMC_SQPIPSRAM_ID_LENGTH_64B SINIT_IDL(0) /*!< SPI PSRAM ID length is 64 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_32B SINIT_IDL(1) /*!< SPI PSRAM ID length is 32 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_16B SINIT_IDL(2) /*!< SPI PSRAM ID length is 16 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_8B SINIT_IDL(3) /*!< SPI PSRAM ID length is 8 bits */ + +/* SPI PSRAM bit number of address phase */ +#define SINIT_ADRBIT(regval) (BITS(24,28) & ((uint32_t)(regval) << 24)) +#define EXMC_SQPIPSRAM_ADDR_LENGTH_1B SINIT_ADRBIT(1) /*!< SPI PSRAM address is 1 bit */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_2B SINIT_ADRBIT(2) /*!< SPI PSRAM address is 2 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_3B SINIT_ADRBIT(3) /*!< SPI PSRAM address is 3 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_4B SINIT_ADRBIT(4) /*!< SPI PSRAM address is 4 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_5B SINIT_ADRBIT(5) /*!< SPI PSRAM address is 5 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_6B SINIT_ADRBIT(6) /*!< SPI PSRAM address is 6 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_7B SINIT_ADRBIT(7) /*!< SPI PSRAM address is 7 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_8B SINIT_ADRBIT(8) /*!< SPI PSRAM address is 8 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_9B SINIT_ADRBIT(9) /*!< SPI PSRAM address is 9 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_10B SINIT_ADRBIT(10) /*!< SPI PSRAM address is 10 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_11B SINIT_ADRBIT(11) /*!< SPI PSRAM address is 11 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_12B SINIT_ADRBIT(12) /*!< SPI PSRAM address is 12 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_13B SINIT_ADRBIT(13) /*!< SPI PSRAM address is 13 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_14B SINIT_ADRBIT(14) /*!< SPI PSRAM address is 14 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_15B SINIT_ADRBIT(15) /*!< SPI PSRAM address is 15 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_16B SINIT_ADRBIT(16) /*!< SPI PSRAM address is 16 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_17B SINIT_ADRBIT(17) /*!< SPI PSRAM address is 17 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_18B SINIT_ADRBIT(18) /*!< SPI PSRAM address is 18 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_19B SINIT_ADRBIT(19) /*!< SPI PSRAM address is 19 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_20B SINIT_ADRBIT(20) /*!< SPI PSRAM address is 20 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_21B SINIT_ADRBIT(21) /*!< SPI PSRAM address is 21 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_22B SINIT_ADRBIT(22) /*!< SPI PSRAM address is 22 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_23B SINIT_ADRBIT(23) /*!< SPI PSRAM address is 23 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_24B SINIT_ADRBIT(24) /*!< SPI PSRAM address is 24 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_25B SINIT_ADRBIT(25) /*!< SPI PSRAM address is 25 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_26B SINIT_ADRBIT(26) /*!< SPI PSRAM address is 26 bits */ + +/* SPI PSRAM bit number of command phase */ +#define SINIT_CMDBIT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_4B SINIT_CMDBIT(0) /*!< SPI PSRAM command is 4 bits */ +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_8B SINIT_CMDBIT(1) /*!< SPI PSRAM command is 8 bits */ +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_16B SINIT_CMDBIT(2) /*!< SPI PSRAM command is 16 bits */ + +/* SPI PSRAM read command mode */ +#define SRCMD_RMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) +#define EXMC_SQPIPSRAM_READ_MODE_DISABLE SRCMD_RMODE(0) /*!< not SPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_SPI SRCMD_RMODE(1) /*!< SPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_SQPI SRCMD_RMODE(2) /*!< SQPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_QPI SRCMD_RMODE(3) /*!< QPI mode */ + +/* SPI PSRAM write command mode */ +#define SRCMD_WMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) +#define EXMC_SQPIPSRAM_WRITE_MODE_DISABLE SRCMD_WMODE(0) /*!< not SPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_SPI SRCMD_WMODE(1) /*!< SPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_SQPI SRCMD_WMODE(2) /*!< SQPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_QPI SRCMD_WMODE(3) /*!< QPI mode */ + +/* read data sample polarity */ +#define EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE ((uint32_t)0x00000000U) /*!< sample data at rising edge */ +#define EXMC_SQPIPSRAM_SAMPLE_FALLING_EDGE EXMC_SINIT_POL /*!< sample data at falling edge */ + +/* SQPI SRAM command flag */ +#define EXMC_SEND_COMMAND_FLAG_RDID EXMC_SRCMD_RDID /*!< EXMC_SRCMD_RDID flag bit */ +#define EXMC_SEND_COMMAND_FLAG_SC EXMC_SWCMD_SC /*!< EXMC_SWCMD_SC flag bit */ + +/* EXMC flag bits */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ +#define EXMC_SDRAM_FLAG_REFRESH EXMC_SDSDAT_REIF /*!< refresh error interrupt flag */ +#define EXMC_SDRAM_FLAG_NREADY EXMC_SDSDAT_NRDY /*!< not ready status */ + +/* EXMC interrupt enable bits */ +#define EXMC_NAND_PCCARD_INT_RISE EXMC_NPINTEN_INTREN /*!< interrupt rising edge detection enable */ +#define EXMC_NAND_PCCARD_INT_LEVEL EXMC_NPINTEN_INTHEN /*!< interrupt high-level detection enable */ +#define EXMC_NAND_PCCARD_INT_FALL EXMC_NPINTEN_INTFEN /*!< interrupt falling edge detection enable */ +#define EXMC_SDRAM_INT_REFRESH EXMC_SDARI_REIE /*!< interrupt refresh error enable */ + +/* EXMC interrupt flag bits */ +#define EXMC_NAND_PCCARD_INT_FLAG_RISE EXMC_NPINTEN_INTREN /*!< interrupt rising edge detection enable */ +#define EXMC_NAND_PCCARD_INT_FLAG_LEVEL EXMC_NPINTEN_INTHEN /*!< interrupt high-level detection enable */ +#define EXMC_NAND_PCCARD_INT_FLAG_FALL EXMC_NPINTEN_INTFEN /*!< interrupt falling edge detection enable */ +#define EXMC_SDRAM_INT_FLAG_REFRESH EXMC_SDARI_REIE /*!< interrupt refresh error enable */ + +/* function declarations */ +/* function configuration */ +/* deinitialize EXMC NOR/SRAM region */ +void exmc_norsram_deinit(uint32_t exmc_norsram_region); +/* exmc_norsram_parameter_struct parameter initialize */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize EXMC NOR/SRAM region */ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* EXMC NOR/SRAM bank enable */ +void exmc_norsram_enable(uint32_t exmc_norsram_region); +/* EXMC NOR/SRAM bank disable */ +void exmc_norsram_disable(uint32_t exmc_norsram_region); + +/* deinitialize EXMC NAND bank */ +void exmc_nand_deinit(uint32_t exmc_nand_bank); +/* exmc_nand_init_struct parameter initialize */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* initialize EXMC NAND bank */ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* EXMC NAND bank enable */ +void exmc_nand_enable(uint32_t exmc_nand_bank); +/* EXMC NAND bank disable */ +void exmc_nand_disable(uint32_t exmc_nand_bank); +/* enable or disable the EXMC NAND ECC function */ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue); +/* get the EXMC ECC value */ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank); + +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* exmc_pccard_parameter_struct parameter initialize */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* EXMC PC card bank enable */ +void exmc_pccard_enable(void); +/* EXMC PC card bank disable */ +void exmc_pccard_disable(void); + +/* deinitialize EXMC SDRAM device */ +void exmc_sdram_deinit(uint32_t exmc_sdram_device); +/* initialize EXMC SDRAM device */ +void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* exmc_sdram_parameter_struct parameter initialize */ +void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* configure the SDRAM memory command */ +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct); +/* set auto-refresh interval */ +void exmc_sdram_refresh_count_set(uint32_t exmc_count); +/* set the number of successive auto-refresh command */ +void exmc_sdram_autorefresh_number_set(uint32_t exmc_number); +/* config the write protection function */ +void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatus newvalue); +/* get the status of SDRAM device0 or device1 */ +uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device); +/* configure the delayed sample clock of read data */ +void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk); +/* enable read sample */ +void exmc_sdram_readsample_enable(void); +/* disable read sample */ +void exmc_sdram_readsample_disable(void); + +/* deinitialize EXMC SQPIPSRAM */ +void exmc_sqpipsram_deinit(void); +/* initialize EXMC SQPIPSRAM */ +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +/* exmc_sqpipsram_parameter_struct parameter initialize */ +void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +/* set the read command */ +void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_wait_cycle, uint32_t read_command_code); +/* set the write command */ +void exmc_sqpipsram_write_command_set(uint32_t write_command_mode, uint32_t write_wait_cycle, uint32_t write_command_code); +/* send SPI read ID command */ +void exmc_sqpipsram_read_id_command_send(void); +/* send SPI special command which does not have address and data phase */ +void exmc_sqpipsram_write_cmd_send(void); +/* get the EXMC SPI ID low data */ +uint32_t exmc_sqpipsram_low_id_get(void); +/* get the EXMC SPI ID high data */ +uint32_t exmc_sqpipsram_high_id_get(void); +/* get the bit value of EXMC send write command bit or read ID command */ +FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag); + +/* interrupt & flag functions */ +/* check EXMC flag is set or not */ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag); +/* clear EXMC flag */ +void exmc_flag_clear(uint32_t bank, uint32_t flag); +/* check EXMC flag is set or not */ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source); +/* clear EXMC flag */ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source); +/* enable EXMC interrupt */ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source); +/* disable EXMC interrupt */ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source); + +#endif /* GD32F20X_EXMC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h new file mode 100644 index 0000000000..54f1faa366 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h @@ -0,0 +1,258 @@ +/*! + \file gd32f20x_exti.h + \brief definitions for the EXTI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_EXTI_H +#define GD32F20X_EXTI_H + +#include "gd32f20x.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ +#define EXTI_INTEN_INTEN19 BIT(19) /*!< interrupt from line 19 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ +#define EXTI_EVEN_EVEN19 BIT(19) /*!< event from line 19 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ +#define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ +#define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ +#define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum +{ + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ + EXTI_19 = BIT(19), /*!< EXTI line 19 */ +}exti_line_enum; + +/* external interrupt and event */ +typedef enum +{ + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +}exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum +{ + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH /*!< EXTI rising and falling edge trigger */ +}exti_trig_type_enum; + +/* function declarations */ +/* initialization, EXTI lines configuration functions */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* interrupt & flag functions */ +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32F20X_EXTI_H */ + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h new file mode 100644 index 0000000000..0d2a2ea9e9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h @@ -0,0 +1,369 @@ +/*! + \file gd32f20x_fmc.h + \brief definitions for the FMC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_FMC_H +#define GD32F20X_FMC_H + +#include "gd32f20x.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0,2) /*!< wait state counter */ + +/* FMC_KEY0 */ +#define FMC_KEY0_KEY BITS(0,31) /*!< FMC_CTL0 unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0,31) /*!< option bytes unlock key bits */ + +/* FMC_STAT0 */ +#define FMC_STAT0_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT0_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT0_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT0_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL0 */ +#define FMC_CTL0_PG BIT(0) /*!< main flash program for bank0 command bit */ +#define FMC_CTL0_PER BIT(1) /*!< main flash page erase for bank0 command bit */ +#define FMC_CTL0_MER BIT(2) /*!< main flash mass erase for bank0 command bit */ +#define FMC_CTL0_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL0_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL0_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL0_LK BIT(7) /*!< FMC_CTL0 lock bit */ +#define FMC_CTL0_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL0_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR0 */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2,9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10,25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0,31) /*!< store WP of option bytes block after system reset */ + +/* FMC_KEY1 */ +#define FMC_KEY1_KEY BITS(0,31) /*!< FMC_CTL1 unlock key bits */ + +/* FMC_STAT1 */ +#define FMC_STAT1_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT1_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT1_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT1_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL1 */ +#define FMC_CTL1_PG BIT(0) /*!< main flash program for bank1 command bit */ +#define FMC_CTL1_PER BIT(1) /*!< main flash page erase for bank1 command bit */ +#define FMC_CTL1_MER BIT(2) /*!< main flash mass erase for bank1 command bit */ +#define FMC_CTL1_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL1_LK BIT(7) /*!< FMC_CTL1 lock bit */ +#define FMC_CTL1_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR1 */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0,31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum +{ + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +}fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum +{ + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ +}fmc_int_enum; + +/* FMC flags */ +typedef enum +{ + FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ + FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ + FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ + FMC_FLAG_BANK0_END = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U), /*!< FMC bank0 end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ + FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ + FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ + FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ +}fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum +{ + FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ + FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ +}fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* unlock the FMC bank0 operation */ +void fmc_bank0_unlock(void); +/* unlock the FMC bank1 operation */ +void fmc_bank1_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* lock the bank0 FMC operation */ +void fmc_bank0_lock(void); +/* lock the bank1 FMC operation */ +void fmc_bank1_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC erase whole bank0 */ +fmc_state_enum fmc_bank0_erase(void); +/* FMC erase whole bank1 */ +fmc_state_enum fmc_bank1_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the option byte */ +fmc_state_enum ob_erase(void); +/* enable write protect */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure the option byte security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* write the FMC option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program option bytes data */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get the FMC option byte user */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get option byte security protection code value */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); +/* check FMC bank0 ready or not */ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + +#endif /* GD32F20X_FMC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h new file mode 100644 index 0000000000..a7c041137b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h @@ -0,0 +1,109 @@ +/*! + \file gd32f20x_fwdgt.h + \brief definitions for the FWDGT + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_FWDGT_H +#define GD32F20X_FWDGT_H + +#include "gd32f20x.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE /*!< FWDGT base address */ + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x04U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x08U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0,15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0,2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0,11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* function configuration */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* interrupt & flag functions */ +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32F20X_FWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h new file mode 100644 index 0000000000..fe29dad0ff --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h @@ -0,0 +1,718 @@ +/*! + \file gd32f20x_gpio.h + \brief definitions for the GPIO + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_GPIO_H +#define GD32F20X_GPIO_H + +#include "gd32f20x.h" + +/* GPIOx(x=A,B,C,D,E,F,G,H,I) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) +#define GPIOF (GPIO_BASE + 0x00001400U) +#define GPIOG (GPIO_BASE + 0x00001800U) +#define GPIOH (GPIO_BASE + 0x00006C00U) +#define GPIOI (GPIO_BASE + 0x00007000U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ +#define AFIO_PCF2 REG32(AFIO + 0x3CU) /*!< AFIO port configuration register 2 */ +#define AFIO_PCF3 REG32(AFIO + 0x40U) /*!< AFIO port configuration register 3 */ +#define AFIO_PCF4 REG32(AFIO + 0x44U) /*!< AFIO port configuration register 4 */ +#define AFIO_PCF5 REG32(AFIO + 0x48U) /*!< AFIO port configuration register 5 */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8,9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10,11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12,13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14,15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16,17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18,19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20,21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22,23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24,25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26,27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28,29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8,9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10,11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12,13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14,15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16,17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18,19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20,21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22,23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24,25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26,27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28,29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0,3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4,6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN0_REMAP BITS(13,14) /*!< CAN0 remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ADC0_ETRGINS_REMAP BIT(17) /*!< ADC 0 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC0_ETRGREG_REMAP BIT(18) /*!< ADC 0 external trigger regular conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGINS_REMAP BIT(19) /*!< ADC 1 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGREG_REMAP BIT(20) /*!< ADC 1 external trigger regular conversion remapping */ +#define AFIO_PCF0_ENET_REMAP BIT(21) /*!< ethernet MAC I/O remapping */ +#define AFIO_PCF0_CAN1_REMAP BIT(22) /*!< CAN1 remapping */ +#define AFIO_PCF0_ENET_PHY_SEL BIT(23) /*!< ethernet MII or RMII PHY selection */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1ITI1_REMAP BIT(29) /*!< TIMER1 internal trigger 1 remapping */ +#define AFIO_PCF0_PTP_PPS_REMAP BIT(30) /*!< ethernet PTP PPS remapping */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0,3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4,7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8,11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12,15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0,3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4,7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8,11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12,15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0,3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4,7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8,11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12,15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0,3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4,7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8,11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12,15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_TIMER8_REMAP BIT(5) /*!< TIMER8 remapping */ +#define AFIO_PCF1_TIMER9_REMAP BIT(6) /*!< TIMER9 remapping */ +#define AFIO_PCF1_TIMER10_REMAP BIT(7) /*!< TIMER10 remapping */ +#define AFIO_PCF1_TIMER12_REMAP BIT(8) /*!< TIMER12 remapping */ +#define AFIO_PCF1_TIMER13_REMAP BIT(9) /*!< TIMER13 remapping */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ + +/* AFIO_PCF2 */ +#define AFIO_PCF2_DCI_VSYNC_REMAP BITS(0,1) /*!< DCI VSYNC remapping */ +#define AFIO_PCF2_DCI_D0_REMAP BITS(2,3) /*!< DCI D0 remapping */ +#define AFIO_PCF2_DCI_D1_REMAP BITS(4,5) /*!< DCI D1 remapping */ +#define AFIO_PCF2_DCI_D2_REMAP BITS(6,7) /*!< DCI D2 remapping */ +#define AFIO_PCF2_DCI_D3_REMAP BITS(8,9) /*!< DCI D3 remapping */ +#define AFIO_PCF2_DCI_D4_REMAP BITS(10,11) /*!< DCI D4 remapping */ +#define AFIO_PCF2_DCI_D5_REMAP BITS(12,13) /*!< DCI D5 remapping */ +#define AFIO_PCF2_DCI_D6_REMAP BITS(14,15) /*!< DCI D6 remapping */ +#define AFIO_PCF2_DCI_D7_REMAP BITS(16,17) /*!< DCI D7 remapping */ +#define AFIO_PCF2_DCI_D8_REMAP BITS(18,19) /*!< DCI D8 remapping */ +#define AFIO_PCF2_DCI_D9_REMAP BITS(20,21) /*!< DCI D9 remapping */ +#define AFIO_PCF2_DCI_D10_REMAP BITS(22,23) /*!< DCI D10 remapping */ +#define AFIO_PCF2_DCI_D11_REMAP BITS(24,25) /*!< DCI D11 remapping */ +#define AFIO_PCF2_DCI_D12_REMAP BIT(26) /*!< DCI D12 remapping */ +#define AFIO_PCF2_DCI_D13_REMAP BITS(27,28) /*!< DCI D13 remapping */ +#define AFIO_PCF2_DCI_HSYNC_REMAP BIT(29) /*!< DCI HSYNC remapping */ +#define AFIO_PCF2_PH01_REMAP BIT(31) /*!< PH0/PH1 remapping */ + +/* AFIO_PCF3 */ +#define AFIO_PCF3_TLI_B5_PA3_REMAP BIT(0) /*!< TLI B5 PA3 remapping */ +#define AFIO_PCF3_TLI_VSYNC_PA4_REMAP BIT(1) /*!< TLI VSYNC PA4 remapping */ +#define AFIO_PCF3_TLI_G2_PA6_REMAP BIT(2) /*!< TLI G2 PA6 remapping */ +#define AFIO_PCF3_TLI_R6_PA8_REMAP BIT(3) /*!< TLI R6 PA8 remapping */ +#define AFIO_PCF3_TLI_R4_PA11_REMAP BIT(4) /*!< TLI R4 PA11 remapping */ +#define AFIO_PCF3_TLI_R5_PA12_REMAP BIT(5) /*!< TLI R5 PA12 remapping */ +#define AFIO_PCF3_TLI_R3_PB0_REMAP BIT(6) /*!< TLI R3 PB0 remapping */ +#define AFIO_PCF3_TLI_R6_PB1_REMAP BIT(7) /*!< TLI R6 PB1 remapping */ +#define AFIO_PCF3_TLI_B6_PB8_REMAP BIT(8) /*!< TLI B6 PB8 remapping */ +#define AFIO_PCF3_TLI_B7_PB9_REMAP BIT(9) /*!< TLI B7 PB9 remapping */ +#define AFIO_PCF3_TLI_G4_PB10_REMAP BIT(10) /*!< TLI G4 PB10 remapping */ +#define AFIO_PCF3_TLI_G5_PB11_REMAP BIT(11) /*!< TLI G5 PB11 remapping */ +#define AFIO_PCF3_TLI_HSYNC_PC6_REMAP BIT(12) /*!< TLI HSYNC PC6 remapping */ +#define AFIO_PCF3_TLI_G6_PC7_REMAP BIT(13) /*!< TLI G6 PC7 remapping */ +#define AFIO_PCF3_TLI_R2_PC10_REMAP BIT(14) /*!< TLI R2 PC10 remapping */ +#define AFIO_PCF3_TLI_G7_PD3_REMAP BIT(15) /*!< TLI G7 PD3 remapping */ +#define AFIO_PCF3_TLI_B2_PD6_REMAP BIT(16) /*!< TLI B2 PD6 remapping */ +#define AFIO_PCF3_TLI_B3_PD10_REMAP BIT(17) /*!< TLI B3 PD10 remapping */ +#define AFIO_PCF3_TLI_B0_PE4_REMAP BIT(18) /*!< TLI B0 PE4 remapping */ +#define AFIO_PCF3_TLI_G0_PE5_REMAP BIT(19) /*!< TLI G0 PE5 remapping */ +#define AFIO_PCF3_TLI_G1_PE6_REMAP BIT(20) /*!< TLI G1 PE6 remapping */ +#define AFIO_PCF3_TLI_G3_PE11_REMAP BIT(21) /*!< TLI G3 PE11 remapping */ +#define AFIO_PCF3_TLI_B4_PE12_REMAP BIT(22) /*!< TLI B4 PE12 remapping */ +#define AFIO_PCF3_TLI_DE_PE13_REMAP BIT(23) /*!< TLI DE PE13 remapping */ +#define AFIO_PCF3_TLI_CLK_PE14_REMAP BIT(24) /*!< TLI CLK PE14 remapping */ +#define AFIO_PCF3_TLI_R7_PE15_REMAP BIT(25) /*!< TLI R7 PE15 remapping */ +#define AFIO_PCF3_TLI_DE_PF10_REMAP BIT(26) /*!< TLI DE PF10 remapping */ +#define AFIO_PCF3_TLI_R7_PG6_REMAP BIT(27) /*!< TLI R7 PG6 remapping */ +#define AFIO_PCF3_TLI_CLK_PG7_REMAP BIT(28) /*!< TLI CLK PG7 remapping */ +#define AFIO_PCF3_TLI_G3_PG10_REMAP BIT(29) /*!< TLI G3 PG10 remapping */ +#define AFIO_PCF3_TLI_B2_PG10_REMAP BIT(30) /*!< TLI B2 PG10 remapping */ +#define AFIO_PCF3_TLI_B3_PG11_REMAP BIT(31) /*!< TLI B3 PG11 remapping */ + +/* AFIO_PCF4 */ +#define AFIO_PCF4_TLI_B4_PG12_REMAP BIT(0) /*!< TLI B4 PG12 remapping */ +#define AFIO_PCF4_TLI_B1_PG12_REMAP BIT(1) /*!< TLI B1 PG12 remapping */ +#define AFIO_PCF4_TLI_R0_PH2_REMAP BIT(2) /*!< TLI R0 PH2 remapping */ +#define AFIO_PCF4_TLI_R1_PH3_REMAP BIT(3) /*!< TLI R1 PH3 remapping */ +#define AFIO_PCF4_TLI_R2_PH8_REMAP BIT(4) /*!< TLI R2 PH8 remapping */ +#define AFIO_PCF4_TLI_R3_PH9_REMAP BIT(5) /*!< TLI R3 PH9 remapping */ +#define AFIO_PCF4_TLI_R4_PH10_REMAP BIT(6) /*!< TLI R4 PH10 remapping */ +#define AFIO_PCF4_TLI_R5_PH11_REMAP BIT(7) /*!< TLI R5 PH11 remapping */ +#define AFIO_PCF4_TLI_R6_PH12_REMAP BIT(8) /*!< TLI R6 PH12 remapping */ +#define AFIO_PCF4_TLI_G2_PH13_REMAP BIT(9) /*!< TLI G2 PH13 remapping */ +#define AFIO_PCF4_TLI_G3_PH14_REMAP BIT(10) /*!< TLI G3 PH14 remapping */ +#define AFIO_PCF4_TLI_G4_PH15_REMAP BIT(11) /*!< TLI G4 PH15 remapping */ +#define AFIO_PCF4_TLI_G5_PI0_REMAP BIT(12) /*!< TLI G5 PI0 remapping */ +#define AFIO_PCF4_TLI_G6_PI1_REMAP BIT(13) /*!< TLI G6 PI1 remapping */ +#define AFIO_PCF4_TLI_G7_PI2_REMAP BIT(14) /*!< TLI G7 PI2 remapping */ +#define AFIO_PCF4_TLI_B4_PI4_REMAP BIT(15) /*!< TLI B4 PI4 remapping */ +#define AFIO_PCF4_TLI_B5_PI5_REMAP BIT(16) /*!< TLI B5 PI5 remapping */ +#define AFIO_PCF4_TLI_B6_PI6_REMAP BIT(17) /*!< TLI B6 PI6 remapping */ +#define AFIO_PCF4_TLI_B7_PI7_REMAP BIT(18) /*!< TLI B7 PI7 remapping */ +#define AFIO_PCF4_TLI_VSYNC_PI9_REMAP BIT(19) /*!< TLI VSYNC PI9 remapping */ +#define AFIO_PCF4_TLI_HSYNC_PI10_REMAP BIT(20) /*!< TLI HSYNC PI10 remapping */ +#define AFIO_PCF4_TLI_R0_PH4_REMAP BIT(21) /*!< TLI R0 PH4 remapping */ +#define AFIO_PCF4_TLI_R1_PI3_REMAP BIT(22) /*!< TLI R1 PI3 remapping */ +#define AFIO_PCF4_SPI1_SCK_REMAP BIT(23) /*!< SPI1 SCK remapping */ +#define AFIO_PCF4_SPI2_MOSI_REMAP BIT(24) /*!< SPI2 MOSI remapping */ + +/* AFIO_PCF5 */ +#define AFIO_PCF5_I2C2_REMAP0 BIT(0) /*!< I2C2 remapping 0 */ +#define AFIO_PCF5_I2C2_REMAP1 BIT(1) /*!< I2C2 remapping 1 */ +#define AFIO_PCF5_TIMER1_CH0_REMAP BIT(2) /*!< TIMER1 CH0 remapping */ +#define AFIO_PCF5_TIMER4_REMAP BIT(3) /*!< TIMER4 remapping */ +#define AFIO_PCF5_TIMER7_CHON_REMAP BITS(4,5) /*!< TIMER7 CHON remapping */ +#define AFIO_PCF5_TIMER7_CH_REMAP BIT(6) /*!< TIMER7 CH remapping */ +#define AFIO_PCF5_I2C1_REMAP BITS(7,8) /*!< I2C1 remapping */ +#define AFIO_PCF5_SPI1_NSCK_REMAP BITS(9,10) /*!< SPI1 NSCK remapping */ +#define AFIO_PCF5_SPI1_IO_REMAP BITS(11,12) /*!< SPI1 IO remapping */ +#define AFIO_PCF5_UART3_REMAP BIT(13) /*!< UART3 remapping */ +#define AFIO_PCF5_TIMER11_REMAP BIT(14) /*!< TIMER11 remapping */ +#define AFIO_PCF5_CAN0_ADD_REMAP BIT(15) /*!< CAN0 ADD remapping */ +#define AFIO_PCF5_ENET_TXD3_REMAP BIT(16) /*!< ENET TXD3 remapping */ +#define AFIO_PCF5_PPS_HI_REMAP BIT(17) /*!< ETH_PPS_OUT remapping */ +#define AFIO_PCF5_ENET_TXD01_REMAP BIT(18) /*!< ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping */ +#define AFIO_PCF5_ENET_CRSCOL_REMAP BIT(19) /*!< ETH_MII_CRS/ETH_MII_COL remapping */ +#define AFIO_PCF5_ENET_RX_HI_REMAP BIT(20) /*!< ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping */ +#define AFIO_PCF5_UART6_REMAP BIT(21) /*!< UART6 remapping */ +#define AFIO_PCF5_USART5_CK_REMAP BIT(22) /*!< USART5 CK remapping */ +#define AFIO_PCF5_USART5_RTS_REMAP BIT(23) /*!< USART5 RTS remapping */ +#define AFIO_PCF5_USART5_CTS_REMAP BIT(24) /*!< USART5 CTS remapping */ +#define AFIO_PCF5_USART5_TX_REMAP BIT(25) /*!< USART5 TX remapping */ +#define AFIO_PCF5_USART5_RX_REMAP BIT(26) /*!< USART5 RX remapping */ +#define AFIO_PCF5_EXMC_SDNWE_REMAP BIT(27) /*!< EXMC SDNWE remapping */ +#define AFIO_PCF5_EXMC_SDCKE0_REMAP BIT(28) /*!< EXMC SDCKE0 remapping */ +#define AFIO_PCF5_EXMC_SDCKE1_REMAP BIT(29) /*!< EXMC SDCKE1 remapping */ +#define AFIO_PCF5_EXMC_SDNE0_REMAP BIT(30) /*!< EXMC SDNE0 remapping */ +#define AFIO_PCF5_EXMC_SDNE1_REMAP BIT(30) /*!< EXMC SDNE1 remapping */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ +#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05U) /*!< output port source F */ +#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06U) /*!< output port source G */ +#define GPIO_PORT_SOURCE_GPIOH ((uint8_t)0x07U) /*!< output port source H */ +#define GPIO_PORT_SOURCE_GPIOI ((uint8_t)0x08U) /*!< output port source I */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ + +/* GPIO remap definitions */ +/* AFIO_PCF0 and AFIO_PCF1 remap definitions */ +#define GPIO_SPI0_REMAP ((uint32_t)0x00000001U) /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP ((uint32_t)0x00000002U) /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP ((uint32_t)0x00000004U) /*!< USART0 remapping */ +#define GPIO_USART1_REMAP ((uint32_t)0x00000008U) /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140010U) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140030U) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160040U) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x001600C0U) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180100U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180200U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180300U) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0800U) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0C00U) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP ((uint32_t)0x00001000U) /*!< TIMER3 remapping */ +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN0 partial remapping */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN0 full remapping */ +#define GPIO_PD01_REMAP ((uint32_t)0x00008000U) /*!< PD01 remapping */ +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200001U) /*!< TIMER4 channel3 internal remapping */ +#define GPIO_ADC0_ETRGINS_REMAP ((uint32_t)0x00200002U) /*!< ADC0 external trigger inserted conversion remapping */ +#define GPIO_ADC0_ETRGREG_REMAP ((uint32_t)0x00200004U) /*!< ADC0 external trigger regular conversion remapping */ +#define GPIO_ADC1_ETRGINS_REMAP ((uint32_t)0x00200008U) /*!< ADC1 external trigger inserted conversion remapping */ +#define GPIO_ADC1_ETRGREG_REMAP ((uint32_t)0x00200010U) /*!< ADC1 external trigger regular conversion remapping */ +#define GPIO_ENET_REMAP ((uint32_t)0x00200020U) /*!< ENET remapping */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200040U) /*!< CAN1 remapping */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300100U) /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */ +#define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300200U) /*!< JTAG-DP disabled and SW-DP enabled */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300400U) /*!< JTAG-DP disabled and SW-DP disabled */ +#define GPIO_SPI2_REMAP ((uint32_t)0x00201100U) /*!< SPI2 remapping */ +#define GPIO_TIMER1ITI1_REMAP ((uint32_t)0x00202000U) /*!< TIMER1 internal trigger 1 remapping */ +#define GPIO_PTP_PPS_REMAP ((uint32_t)0x00204000U) /*!< ethernet PTP PPS remapping */ +#define GPIO_TIMER8_REMAP ((uint32_t)0x80000020U) /*!< TIMER8 remapping */ +#define GPIO_TIMER9_REMAP ((uint32_t)0x80000040U) /*!< TIMER9 remapping */ +#define GPIO_TIMER10_REMAP ((uint32_t)0x80000080U) /*!< TIMER10 remapping */ +#define GPIO_TIMER12_REMAP ((uint32_t)0x80000100U) /*!< TIMER12 remapping */ +#define GPIO_TIMER13_REMAP ((uint32_t)0x80000200U) /*!< TIMER13 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000400U) /*!< EXMC_NADV connect/disconnect */ + +/* AFIO_PCF2 remap definitions */ +#define GPIO_PCF2_DCI_VSYNC_PG9_REMAP ((uint32_t)0x00000001U) /*!< DCI VSYNC remapped to PG9 */ +#define GPIO_PCF2_DCI_VSYNC_PI5_REMAP ((uint32_t)0x00000003U) /*!< DCI VSYNC remapped to PI5 */ +#define GPIO_PCF2_DCI_D0_PC6_REMAP ((uint32_t)0x00000004U) /*!< DCI D0 remapped to PC6 */ +#define GPIO_PCF2_DCI_D0_PH9_REMAP ((uint32_t)0x0000000CU) /*!< DCI D0 remapped to PH9 */ +#define GPIO_PCF2_DCI_D1_PC7_REMAP ((uint32_t)0x00000010U) /*!< DCI D1 remapped to PC7 */ +#define GPIO_PCF2_DCI_D1_PH10_REMAP ((uint32_t)0x00000030U) /*!< DCI D1 remapped to PH10 */ +#define GPIO_PCF2_DCI_D2_PE0_REMAP ((uint32_t)0x00000040U) /*!< DCI D2 remapped to PE0 */ +#define GPIO_PCF2_DCI_D2_PG10_REMAP ((uint32_t)0x00000080U) /*!< DCI D2 remapped to PG10 */ +#define GPIO_PCF2_DCI_D2_PH11_REMAP ((uint32_t)0x000000C0U) /*!< DCI D2 remapped to PH11 */ +#define GPIO_PCF2_DCI_D3_PE1_REMAP ((uint32_t)0x00000100U) /*!< DCI D3 remapped to PE1 */ +#define GPIO_PCF2_DCI_D3_PG11_REMAP ((uint32_t)0x00000200U) /*!< DCI D3 remapped to PG11 */ +#define GPIO_PCF2_DCI_D3_PH12_REMAP ((uint32_t)0x00000300U) /*!< DCI D3 remapped to PH12 */ +#define GPIO_PCF2_DCI_D4_PE4_REMAP ((uint32_t)0x00000400U) /*!< DCI D4 remapped to PE4 */ +#define GPIO_PCF2_DCI_D4_PH14_REMAP ((uint32_t)0x00000C00U) /*!< DCI D4 remapped to PH14 */ +#define GPIO_PCF2_DCI_D5_PD3_REMAP ((uint32_t)0x00001000U) /*!< DCI D5 remapped to PD3 */ +#define GPIO_PCF2_DCI_D5_PI4_REMAP ((uint32_t)0x00003000U) /*!< DCI D5 remapped to PI4 */ +#define GPIO_PCF2_DCI_D6_PE5_REMAP ((uint32_t)0x00004000U) /*!< DCI D6 remapped to PE5 */ +#define GPIO_PCF2_DCI_D6_PI6_REMAP ((uint32_t)0x0000C000U) /*!< DCI D6 remapped to PI6 */ +#define GPIO_PCF2_DCI_D7_PE6_REMAP ((uint32_t)0x00010000U) /*!< DCI D7 remapped to PE6 */ +#define GPIO_PCF2_DCI_D7_PI7_REMAP ((uint32_t)0x00030000U) /*!< DCI D7 remapped to PI7 */ +#define GPIO_PCF2_DCI_D8_PH6_REMAP ((uint32_t)0x00040000U) /*!< DCI D8 remapped to PH6 */ +#define GPIO_PCF2_DCI_D8_PI1_REMAP ((uint32_t)0x000C0000U) /*!< DCI D8 remapped to PI1 */ +#define GPIO_PCF2_DCI_D9_PH7_REMAP ((uint32_t)0x00100000U) /*!< DCI D9 remapped to PH7 */ +#define GPIO_PCF2_DCI_D9_PI2_REMAP ((uint32_t)0x00300000U) /*!< DCI D9 remapped to PI2 */ +#define GPIO_PCF2_DCI_D10_PD6_REMAP ((uint32_t)0x00400000U) /*!< DCI D10 remapped to PD6 */ +#define GPIO_PCF2_DCI_D10_PI3_REMAP ((uint32_t)0x00C00000U) /*!< DCI D10 remapped to PI3 */ +#define GPIO_PCF2_DCI_D11_PF10_REMAP ((uint32_t)0x01000000U) /*!< DCI D11 remapped to PF10 */ +#define GPIO_PCF2_DCI_D11_PH15_REMAP ((uint32_t)0x03000000U) /*!< DCI D11 remapped to PH15 */ +#define GPIO_PCF2_DCI_D12_PG6_REMAP ((uint32_t)0x04000000U) /*!< DCI D12 remapped to PG6 */ +#define GPIO_PCF2_DCI_D13_PG15_REMAP ((uint32_t)0x08000000U) /*!< DCI D12 remapped to PG15 */ +#define GPIO_PCF2_DCI_D13_PI0_REMAP ((uint32_t)0x18000000U) /*!< DCI D13 remapped to PI0 */ +#define GPIO_PCF2_DCI_HSYNC_PH8_REMAP ((uint32_t)0x20000000U) /*!< DCI HSYNC to PH8 */ +#define GPIO_PCF2_PH01_REMAP ((uint32_t)0x80000000U) /*!< PH0/PH1 remapping */ + +/* AFIO_PCF3 remap definitions */ +#define GPIO_PCF3_TLI_B5_PA3_REMAP ((uint32_t)0x00000001U) /*!< TLI B5 remapped to PA3 */ +#define GPIO_PCF3_TLI_VSYNC_PA4_REMAP ((uint32_t)0x00000002U) /*!< TLI VSYNC remapped to PA4 */ +#define GPIO_PCF3_TLI_G2_PA6_REMAP ((uint32_t)0x00000004U) /*!< TLI G2 remapped to PA6 */ +#define GPIO_PCF3_TLI_R6_PA8_REMAP ((uint32_t)0x00000008U) /*!< TLI R6 remapped to PA8 */ +#define GPIO_PCF3_TLI_R4_PA11_REMAP ((uint32_t)0x00000010U) /*!< TLI R4 remapped to PA11 */ +#define GPIO_PCF3_TLI_R5_PA12_REMAP ((uint32_t)0x00000020U) /*!< TLI R5 remapped to PA12 */ +#define GPIO_PCF3_TLI_R3_PB0_REMAP ((uint32_t)0x00000040U) /*!< TLI R3 remapped to PB0 */ +#define GPIO_PCF3_TLI_R6_PB1_REMAP ((uint32_t)0x00000080U) /*!< TLI R6 remapped to PB1 */ +#define GPIO_PCF3_TLI_B6_PB8_REMAP ((uint32_t)0x00000100U) /*!< TLI B6 remapped to PB8 */ +#define GPIO_PCF3_TLI_B7_PB9_REMAP ((uint32_t)0x00000200U) /*!< TLI B7 remapped to PB9 */ +#define GPIO_PCF3_TLI_G4_PB10_REMAP ((uint32_t)0x00000400U) /*!< TLI G4 remapped to PB10 */ +#define GPIO_PCF3_TLI_G5_PB11_REMAP ((uint32_t)0x00000800U) /*!< TLI G5 remapped to PB11 */ +#define GPIO_PCF3_TLI_HSYNC_PC6_REMAP ((uint32_t)0x00001000U) /*!< TLI HSYNC remapped to PC6 */ +#define GPIO_PCF3_TLI_G6_PC7_REMAP ((uint32_t)0x00002000U) /*!< TLI G6 remapped to PC7 */ +#define GPIO_PCF3_TLI_R2_PC10_REMAP ((uint32_t)0x00004000U) /*!< TLI R2 remapped to PC10 */ +#define GPIO_PCF3_TLI_G7_PD3_REMAP ((uint32_t)0x00008000U) /*!< TLI G7 remapped to PD3 */ +#define GPIO_PCF3_TLI_B2_PD6_REMAP ((uint32_t)0x00010000U) /*!< TLI B2 remapped to PD6 */ +#define GPIO_PCF3_TLI_B3_PD10_REMAP ((uint32_t)0x00020000U) /*!< TLI B3 remapped to PD10 */ +#define GPIO_PCF3_TLI_B0_PE4_REMAP ((uint32_t)0x00040000U) /*!< TLI B0 remapped to PE4 */ +#define GPIO_PCF3_TLI_G0_PE5_REMAP ((uint32_t)0x00080000U) /*!< TLI G0 remapped to PE5 */ +#define GPIO_PCF3_TLI_G1_PE6_REMAP ((uint32_t)0x00100000U) /*!< TLI G1 remapped to PE6 */ +#define GPIO_PCF3_TLI_G3_PE11_REMAP ((uint32_t)0x00200000U) /*!< TLI G3 remapped to PE11 */ +#define GPIO_PCF3_TLI_B4_PE12_REMAP ((uint32_t)0x00400000U) /*!< TLI B4 remapped to PE12 */ +#define GPIO_PCF3_TLI_DE_PE13_REMAP ((uint32_t)0x00800000U) /*!< TLI DE remapped to PE13 */ +#define GPIO_PCF3_TLI_CLK_PE14_REMAP ((uint32_t)0x01000000U) /*!< TLI CLK remapped to PE14 */ +#define GPIO_PCF3_TLI_R7_PE15_REMAP ((uint32_t)0x02000000U) /*!< TLI R7 remapped to PE15 */ +#define GPIO_PCF3_TLI_DE_PF10_REMAP ((uint32_t)0x04000000U) /*!< TLI DE remapped to PF10 */ +#define GPIO_PCF3_TLI_R7_PG6_REMAP ((uint32_t)0x08000000U) /*!< TLI R7 remapped to PG6 */ +#define GPIO_PCF3_TLI_CLK_PG7_REMAP ((uint32_t)0x10000000U) /*!< TLI CLK remapped to PG7 */ +#define GPIO_PCF3_TLI_G3_PG10_REMAP ((uint32_t)0x20000000U) /*!< TLI G3 remapped to PG10 */ +#define GPIO_PCF3_TLI_B2_PG10_REMAP ((uint32_t)0x40000000U) /*!< TLI B2 remapped to PG10 */ +#define GPIO_PCF3_TLI_B3_PG11_REMAP ((uint32_t)0x80000000U) /*!< TLI B3 remapped to PG11 */ + +/* AFIO_PCF4 remap definitions */ +#define GPIO_PCF4_TLI_B4_PG12_REMAP ((uint32_t)0x00000001U) /*!< TLI B4 remapped to PG12 */ +#define GPIO_PCF4_TLI_B1_PG12_REMAP ((uint32_t)0x00000002U) /*!< TLI B1 remapped to PG12 */ +#define GPIO_PCF4_TLI_R0_PH2_REMAP2 ((uint32_t)0x00000004U) /*!< TLI R0 remapped to PH2 */ +#define GPIO_PCF4_TLI_R1_PH3_REMAP ((uint32_t)0x00000008U) /*!< TLI R1 remapped to PH3 */ +#define GPIO_PCF4_TLI_R2_PH8_REMAP ((uint32_t)0x00000010U) /*!< TLI R2 remapped to PH8 */ +#define GPIO_PCF4_TLI_R3_PH9_REMAP ((uint32_t)0x00000020U) /*!< TLI R3 remapped to PH9 */ +#define GPIO_PCF4_TLI_R4_PH10_REMAP ((uint32_t)0x00000040U) /*!< TLI R4 remapped to PH10 */ +#define GPIO_PCF4_TLI_R5_PH11_REMAP ((uint32_t)0x00000080U) /*!< TLI R5 remapped to PH11 */ +#define GPIO_PCF4_TLI_R6_PH12_REMAP ((uint32_t)0x00000100U) /*!< TLI R6 remapped to PH12 */ +#define GPIO_PCF4_TLI_G2_PH13_REMAP ((uint32_t)0x00000200U) /*!< TLI G2 remapped to PH13 */ +#define GPIO_PCF4_TLI_G3_PH14_REMAP ((uint32_t)0x00000400U) /*!< TLI G3 remapped to PH14 */ +#define GPIO_PCF4_TLI_G4_PH15_REMAP ((uint32_t)0x00000800U) /*!< TLI G4 remapped to PH15 */ +#define GPIO_PCF4_TLI_G5_PI0_REMAP ((uint32_t)0x00001000U) /*!< TLI G5 remapped to PI0 */ +#define GPIO_PCF4_TLI_G6_PI1_REMAP ((uint32_t)0x00002000U) /*!< TLI G6 remapped to PI1 */ +#define GPIO_PCF4_TLI_G7_PI2_REMAP ((uint32_t)0x00004000U) /*!< TLI G7 remapped to PI2 */ +#define GPIO_PCF4_TLI_B4_PI4_REMAP ((uint32_t)0x00008000U) /*!< TLI B4 remapped to PI4 */ +#define GPIO_PCF4_TLI_B5_PI5_REMAP ((uint32_t)0x00010000U) /*!< TLI B5 remapped to PI5 */ +#define GPIO_PCF4_TLI_B6_PI6_REMAP ((uint32_t)0x00020000U) /*!< TLI B6 remapped to PI6 */ +#define GPIO_PCF4_TLI_B7_PI7_REMAP ((uint32_t)0x00040000U) /*!< TLI B7 remapped to PI7 */ +#define GPIO_PCF4_TLI_VSYNC_PI9_REMAP ((uint32_t)0x00080000U) /*!< TLI VSYNC remapped to PI9 */ +#define GPIO_PCF4_TLI_HSYNC_PI10_REMAP ((uint32_t)0x00100000U) /*!< TLI HSYNC remapped to PI10 */ +#define GPIO_PCF4_TLI_R0_PH4_REMAP ((uint32_t)0x00200000U) /*!< TLI R0 remapped to PH4 */ +#define GPIO_PCF4_TLI_R1_PI3_REMAP ((uint32_t)0x00400000U) /*!< TLI R1 remapped to PI3 */ +#define GPIO_PCF4_SPI1_SCK_PD3_REMAP ((uint32_t)0x00800000U) /*!< SPI1 SCK remapped to PD3 */ +#define GPIO_PCF4_SPI2_MOSI_PD6_REMAP ((uint32_t)0x01000000U) /*!< SPI2 MOSI remapped to PD6 */ + +/* AFIO_PCF5 remap definitions */ +#define GPIO_PCF5_I2C2_REMAP0 ((uint32_t)0x00000001U) /*!< I2C2 remapping 0 */ +#define GPIO_PCF5_I2C2_REMAP1 ((uint32_t)0x00000002U) /*!< I2C2 remapping 1 */ +#define GPIO_PCF5_TIMER1_CH0_REMAP ((uint32_t)0x00000004U) /*!< TIMER1 CH0 remapped to PA5 */ +#define GPIO_PCF5_TIMER4_REMAP ((uint32_t)0x00000008U) /*!< TIMER4 CH0 remapping */ +#define GPIO_PCF5_TIMER7_CHON_REMAP0 ((uint32_t)0x00000020U) /*!< TIMER7 CHON remapping 0 */ +#define GPIO_PCF5_TIMER7_CHON_REMAP1 ((uint32_t)0x00000030U) /*!< TIMER7 CHON remapping 1 */ +#define GPIO_PCF5_TIMER7_CH_REMAP ((uint32_t)0x00000040U) /*!< TIMER7 CH remapping */ +#define GPIO_PCF5_I2C1_REMAP0 ((uint32_t)0x00000100U) /*!< I2C1 remapping 0 */ +#define GPIO_PCF5_I2C1_REMAP1 ((uint32_t)0x00000180U) /*!< I2C1 remapping 1 */ +#define GPIO_PCF5_SPI1_NSCK_REMAP0 ((uint32_t)0x00000400U) /*!< SPI1 NSS/SCK remapping 0 */ +#define GPIO_PCF5_SPI1_NSCK_REMAP1 ((uint32_t)0x00000600U) /*!< SPI1 NSS/SCK remapping 1 */ +#define GPIO_PCF5_SPI1_IO_REMAP0 ((uint32_t)0x00000800U) /*!< SPI1 MISO/MOSI remapping 0 */ +#define GPIO_PCF5_SPI1_IO_REMAP1 ((uint32_t)0x00001800U) /*!< SPI1 MISO/MOSI remapping 1 */ +#define GPIO_PCF5_UART3_REMAP ((uint32_t)0x00002000U) /*!< UART3 remapping */ +#define GPIO_PCF5_TIMER11_REMAP ((uint32_t)0x00004000U) /*!< TIMER11 remapping */ +#define GPIO_PCF5_CAN0_ADD_REMAP ((uint32_t)0x00008000U) /*!< CAN0 addition remapping */ +#define GPIO_PCF5_ENET_TXD3_REMAP ((uint32_t)0x00010000U) /*!< ETH_TXD3 remapped to PE2 */ +#define GPIO_PCF5_PPS_HI_REMAP ((uint32_t)0x00020000U) /*!< ETH_PPS_OUT remapped to PG8 */ +#define GPIO_PCF5_ENET_TXD01_REMAP ((uint32_t)0x00040000U) /*!< ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping */ +#define GPIO_PCF5_ENET_CRSCOL_REMAP ((uint32_t)0x00080000U) /*!< ETH_MII_CRS/ETH_MII_COL remapping */ +#define GPIO_PCF5_ENET_RX_HI_REMAP ((uint32_t)0x00100000U) /*!< ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping */ +#define GPIO_PCF5_UART6_REMAP ((uint32_t)0x00200000U) /*!< UART6 remapping */ +#define GPIO_PCF5_USART5_CK_PG7_REMAP ((uint32_t)0x00400000U) /*!< USART5 CK remapped to PG7 */ +#define GPIO_PCF5_USART5_RTS_PG12_REMAP ((uint32_t)0x00800000U) /*!< USART5 RTS remapped to PG12 */ +#define GPIO_PCF5_USART5_CTS_PG13_REMAP ((uint32_t)0x01000000U) /*!< USART5 CTS remapped to PG13 */ +#define GPIO_PCF5_USART5_TX_PG14_REMAP ((uint32_t)0x02000000U) /*!< USART5 TX remapped to PG14 */ +#define GPIO_PCF5_USART5_RX_PG9_REMAP ((uint32_t)0x04000000U) /*!< USART5 RX remapped to PG9 */ +#define GPIO_PCF5_EXMC_SDNWE_PC0_REMAP ((uint32_t)0x08000000U) /*!< EXMC SDNWE remapped to PC0 */ +#define GPIO_PCF5_EXMC_SDCKE0_PC3_REMAP ((uint32_t)0x10000000U) /*!< EXMC SDCKE0 remapped to PC3 */ +#define GPIO_PCF5_EXMC_SDCKE1_PB5_REMAP ((uint32_t)0x20000000U) /*!< EXMC SDCKE1 remapped to PB5 */ +#define GPIO_PCF5_EXMC_SDNE0_PC2_REMAP ((uint32_t)0x40000000U) /*!< EXMC SDNE0 remapped to PC2 */ +#define GPIO_PCF5_EXMC_SDNE1_PB6_REMAP ((uint32_t)0x80000000U) /*!< EXMC SDNE1 remapped to PB6 */ + +/* AFIO port configuration register selection */ +#define GPIO_PCF2 ((uint8_t)0x02U) /*!< AFIO port configuration register 2 */ +#define GPIO_PCF3 ((uint8_t)0x03U) /*!< AFIO port configuration register 3 */ +#define GPIO_PCF4 ((uint8_t)0x04U) /*!< AFIO port configuration register 4 */ +#define GPIO_PCF5 ((uint8_t)0x05U) /*!< AFIO port configuration register 5*/ + +/* ethernet MII or RMII PHY selection */ +#define GPIO_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< configure ethernet MAC for connection with an MII PHY */ +#define GPIO_ENET_PHY_RMII AFIO_PCF0_ENET_PHY_SEL /*!< configure ethernet MAC for connection with an RMII PHY */ + +/* function declarations */ +/* initialization functions */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin); + +/* function configuration */ +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); + +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue); +/* configure GPIO pin remap1 */ +void gpio_pin_remap1_config(uint8_t remap_reg, uint32_t remap, ControlStatus newvalue); + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); + +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t enet_sel); + +#endif /* GD32F20X_GPIO_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h new file mode 100644 index 0000000000..069574a943 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h @@ -0,0 +1,208 @@ +/*! + \file gd32f20x_hau.h + \brief definitions for the HAU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_HAU_H +#define GD32F20X_HAU_H + +#include "gd32f20x.h" + +/* HAU definitions */ +#define HAU HAU_BASE + +/* registers definitions */ +#define HAU_CTL REG32(HAU + 0x00U) /*!< control register */ +#define HAU_DI REG32(HAU + 0x04U) /*!< data input register */ +#define HAU_CFG REG32(HAU + 0x08U) /*!< configuration register */ +#define HAU_DO0 REG32(HAU + 0x0CU) /*!< data output register 0 */ +#define HAU_DO1 REG32(HAU + 0x10U) /*!< data output register 1 */ +#define HAU_DO2 REG32(HAU + 0x14U) /*!< data output register 2 */ +#define HAU_DO3 REG32(HAU + 0x18U) /*!< data output register 3 */ +#define HAU_DO4 REG32(HAU + 0x1CU) /*!< data output register 4 */ +#define HAU_DO5 REG32(HAU + 0x324U) /*!< data output register 5 */ +#define HAU_DO6 REG32(HAU + 0x328U) /*!< data output register 6 */ +#define HAU_DO7 REG32(HAU + 0x32CU) /*!< data output register 7 */ +#define HAU_INTEN REG32(HAU + 0x20U) /*!< interrupt enable register */ +#define HAU_STAT REG32(HAU + 0x24U) /*!< status and interrupt flag register */ + +/* bits definitions */ +/* HAU_CTL */ +#define HAU_CTL_START BIT(2) /*!< set to 1 to reset the HAU processor core, so that it is ready to start the digest calculation */ +#define HAU_CTL_DMAE BIT(3) /*!< DMA enable */ +#define HAU_CTL_DATAM BITS(4,5) /*!< data type mode */ +#define HAU_CTL_HMS BIT(6) /*!< HAU mode selection */ +#define HAU_CTL_ALGM_0 BIT(7) /*!< algorithm selection bit 0 */ +#define HAU_CTL_NWIF BITS(8,11) /*!< number of words in the input FIFO */ +#define HAU_CTL_DINE BIT(12) /*!< DI register not empty */ +#define HAU_CTL_MDS BIT(13) /*!< multiple DMA selection */ +#define HAU_CTL_KLM BIT(16) /*!< key length mode */ +#define HAU_CTL_ALGM_1 BIT(18) /*!< algorithm selection bit 1 */ + +/* HAU_DI */ +#define HAU_DI_DI BITS(0,31) /*!< message data input */ + +/* HAU_CFG */ +#define HAU_CFG_VBL BITS(0,4) /*!< valid bits length in the last word */ +#define HAU_CFG_CALEN BIT(8) /*!< digest calculation enable */ + +/* HAU_DOx x=0..7 */ +#define HAU_DOX_DOX BITS(0,31) /*!< message digest result of hash algorithm */ + +/* HAU_INTEN */ +#define HAU_INTEN_DIIE BIT(0) /*!< data input interrupt enable */ +#define HAU_INTEN_CCIE BIT(1) /*!< calculation completion interrupt enable */ + +/* HAU_STAT */ +#define HAU_STAT_DINT BIT(0) /*!< data input interrupt flag */ +#define HAU_STAT_CINT BIT(1) /*!< digest calculation completion interrupt flag */ +#define HAU_STAT_DMAS BIT(2) /*!< DMA status */ +#define HAU_STAT_BUSY BIT(3) /*!< busy bit */ + +/* constants definitions */ +/* structure for initialization of the hau */ +typedef struct +{ + uint32_t algo; /*!< algorithm selection */ + uint32_t mode; /*!< HAU mode selection */ + uint32_t datatype; /*!< data type mode */ + uint32_t keytype; /*!< key length mode */ +}hau_init_parameter_struct; + +/* structure for message digest result of the hau */ +typedef struct +{ + uint32_t out[8]; /* message digest result 0-7 */ +}hau_digest_parameter_struct; + +/* hau_ctl register value */ +#define HAU_ALGO_SHA1 ((uint32_t)0x00000000U) /*!< HAU function is SHA1 */ +#define HAU_ALGO_SHA224 HAU_CTL_ALGM_1 /*!< HAU function is SHA224 */ +#define HAU_ALGO_SHA256 (HAU_CTL_ALGM_1 | HAU_CTL_ALGM_0) /*!< HAU function is SHA256 */ +#define HAU_ALGO_MD5 HAU_CTL_ALGM_0 /*!< HAU function is MD5 */ + +#define HAU_MODE_HASH ((uint32_t)0x00000000U) /*!< HAU mode is HASH */ +#define HAU_MODE_HMAC HAU_CTL_HMS /*!< HAU mode is HMAC */ + +#define CTL_DATAM_1(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to HAU_CTL_DATAM bit field */ +#define HAU_SWAPPING_32BIT CTL_DATAM_1(0) /*!< no swapping */ +#define HAU_SWAPPING_16BIT CTL_DATAM_1(1) /*!< half-word swapping */ +#define HAU_SWAPPING_8BIT CTL_DATAM_1(2) /*!< bytes swapping */ +#define HAU_SWAPPING_1BIT CTL_DATAM_1(3) /*!< bit swapping */ + +#define HAU_KEY_SHORTER_64 ((uint32_t)0x00000000U) /*!< HMAC key is <= 64 bytes */ +#define HAU_KEY_LONGGER_64 HAU_CTL_KLM /*!< HMAC key is > 64 bytes */ + +#define GET_CTL_NWIF(regval) GET_BITS((regval),8,11) /*!< get value of HAU_CTL_NWIF bit field */ + +#define SINGLE_DMA_AUTO_DIGEST ((uint32_t)0x00000000U) /*!< message padding and message digest calculation at the end of a DMA transfer */ +#define MULTIPLE_DMA_NO_DIGEST HAU_CTL_MDS /*!< multiple DMA transfers needed and CALEN bit is not automatically set at the end of a DMA transfer */ + +/* hau_cfg register value */ +#define CFG_VBL(regval) (BITS(0,4) & ((regval) << 0)) /*!< write value to HAU_CFG_VBL bit field */ + +/* hau_inten register value */ +#define HAU_INT_DATA_INPUT HAU_INTEN_DIIE /*!< a new block can be entered into the IN buffer */ +#define HAU_INT_CALCULATION_COMPLETE HAU_INTEN_CCIE /*!< calculation complete */ + +#define HAU_FLAG_DATA_INPUT HAU_STAT_DINT /*!< there is enough space (16 bytes) in the input FIFO */ +#define HAU_FLAG_CALCULATION_COMPLETE HAU_STAT_CINT /*!< digest calculation is completed */ +#define HAU_FLAG_DMA HAU_STAT_DMAS /*!< DMA is enabled (DMAE =1) or a transfer is processing */ +#define HAU_FLAG_BUSY HAU_STAT_BUSY /*!< data block is in process */ +#define HAU_FLAG_INFIFO_NO_EMPTY HAU_CTL_DINE /*!< the input FIFO is not empty */ + +#define HAU_INT_FLAG_DATA_INPUT HAU_STAT_DINT /*!< there is enough space (16 bytes) in the input FIFO */ +#define HAU_INT_FLAG_CALCULATION_COMPLETE HAU_STAT_CINT /*!< digest calculation is completed */ + +/* function declarations */ +/* initialization functions */ +/* reset the HAU peripheral */ +void hau_deinit(void); +/* initialize the HAU peripheral parameters */ +void hau_init(hau_init_parameter_struct* initpara); +/* initialize the structure hau_initpara */ +void hau_init_parameter_init(hau_init_parameter_struct* initpara); +/* reset the HAU processor core */ +void hau_reset(void); +/* configure the number of valid bits in last word of the message */ +void hau_last_word_validbits_num_config(uint32_t valid_num); +/* write data to the IN FIFO */ +void hau_data_write(uint32_t data); +/* return the number of words already written into the IN FIFO */ +uint32_t hau_infifo_words_num_get(void); +/* read the message digest result */ +void hau_digest_read(hau_digest_parameter_struct* digestpara); +/* enable digest calculation */ +void hau_digest_calculation_enable(void); +/* configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not */ +void hau_multiple_single_dma_config(uint32_t multi_single); +/* enable the HAU DMA interface */ +void hau_dma_enable(void); +/* disable the HAU DMA interface */ +void hau_dma_disable(void); + +/* calculate digest in HASH mode */ +/* calculate digest using SHA1 in HASH mode */ +ErrStatus hau_hash_sha_1(uint8_t *input, uint32_t in_length, uint8_t output[20]); +/* calculate digest using SHA1 in HMAC mode */ +ErrStatus hau_hmac_sha_1(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[20]); +/* calculate digest using SHA224 in HASH mode */ +ErrStatus hau_hash_sha_224(uint8_t *input, uint32_t in_length, uint8_t output[28]); +/* calculate digest using SHA224 in HMAC mode */ +ErrStatus hau_hmac_sha_224(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[28]); +/* calculate digest using SHA256 in HASH mode */ +ErrStatus hau_hash_sha_256(uint8_t *input, uint32_t in_length, uint8_t output[32]); +/* calculate digest using SHA256 in HMAC mode */ +ErrStatus hau_hmac_sha_256(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[32]); +/* calculate digest using MD5 in HASH mode */ +ErrStatus hau_hash_md5(uint8_t *input, uint32_t in_length, uint8_t output[16]); +/* calculate digest using MD5 in HMAC mode */ +ErrStatus hau_hmac_md5(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[16]); + +/* interrupt & flag functions */ +/* get the HAU flag status */ +FlagStatus hau_flag_get(uint32_t flag); +/* clear the HAU flag status */ +void hau_flag_clear(uint32_t flag); +/* enable the HAU interrupts */ +void hau_interrupt_enable(uint32_t interrupt); +/* disable the HAU interrupts */ +void hau_interrupt_disable(uint32_t interrupt); +/* get the HAU interrupt flag status */ +FlagStatus hau_interrupt_flag_get(uint32_t int_flag); +/* clear the HAU interrupt flag status */ +void hau_interrupt_flag_clear(uint32_t int_flag); + +#endif /*GD32F20X_HAU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h new file mode 100644 index 0000000000..f47b35af05 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h @@ -0,0 +1,352 @@ +/*! + \file gd32f20x_i2c.h + \brief definitions for the I2C + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-04-16, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_I2C_H +#define GD32F20X_I2C_H + +#include "gd32f20x.h" + +/* I2Cx(x=0,1,2) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ +#define I2C2 (I2C_BASE + 0x00006C00U) /*!< I2C2 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ + +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_DISSTRC BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TRS BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_ECV BITS(8,15) /*!< packet error checking register */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0,5) /*!< maximum rise time in fast/standard mode (Master mode) */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ +#define I2C_SAMCS_REG_OFFSET 0x80U /*!< SAMCS register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +}i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_DISABLE ((uint32_t)0x00000000U) /*!< SCL stretching is disabled */ +#define I2C_SCLSTRETCH_ENABLE I2C_CTL0_DISSTRC /*!< SCL stretching is enabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP is enabled */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP is disabled */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* initialization functions */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); + +/* function configuration */ +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* interrupt & flag functions */ +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32F20X_I2C_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h new file mode 100644 index 0000000000..98b68d5189 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h @@ -0,0 +1,96 @@ +/*! + \file gd32f20x_misc.h + \brief definitions for the MISC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_MISC_H +#define GD32F20X_MISC_H + +#include "gd32f20x.h" + +/* constants definitions */ +/* set the RAM and FLASH base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ + +/* set the NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) /*!< NVIC vector table offset mask */ + +/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) /*!< NVIC VECTKEY mask */ + +/* priority group - define the pre-emption priority and the subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ + +/* choose the method to enter or exit the lowpower mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ + +#define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT /*!< low power mode by exiting from ISR */ +#define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP /*!< DEEPSLEEP mode or SLEEP mode */ +#define SCB_LPM_WAKE_BY_ALL_INT SCB_SCR_SEVONPEND /*!< wakeup by all interrupt */ + +/* choose the systick clock source */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */ +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ + +/* function declarations */ +/* function configuration */ +/* set the priority group */ +void nvic_priority_group_set(uint32_t nvic_prigroup); + +/* enable NVIC request */ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); +/* disable NVIC request */ +void nvic_irq_disable(uint8_t nvic_irq); + +/* set the NVIC vector table base address */ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); + +/* set the state of the low power mode */ +void system_lowpower_set(uint8_t lowpower_mode); +/* reset the state of the low power mode */ +void system_lowpower_reset(uint8_t lowpower_mode); + +/* set the systick clock source */ +void systick_clksource_set(uint32_t systick_clksource); + +#endif /* GD32F20X_MISC_H */ + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h new file mode 100644 index 0000000000..9bb936a424 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h @@ -0,0 +1,129 @@ +/*! + \file gd32f20x_pmu.h + \brief definitions for the PMU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_PMU_H +#define GD32F20X_PMU_H + +#include "gd32f20x.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5,7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval) << 5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.5V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 2.8V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 2.9V */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* initialization functions */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable write access to the registers in backup domain */ +void pmu_backup_write_enable(void); +/* disable write access to the registers in backup domain */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); + +#endif /* GD32F20X_PMU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h new file mode 100644 index 0000000000..d95a78bcfe --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h @@ -0,0 +1,1086 @@ +/*! + \file gd32f20x_rcu.h + \brief definitions for the RCU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_RCU_H +#define GD32F20X_RCU_H + +#include "gd32f20x.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHB1EN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHB1RST REG32(RCU + 0x28U) /*!< AHB1 reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#define RCU_AHB2EN REG32(RCU + 0x60U) /*!< AHB2 enable register */ +#define RCU_ADDAPB2EN REG32(RCU + 0x64U) /*!< APB2 additional enable register */ +#define RCU_ADDAPB1EN REG32(RCU + 0x68U) /*!< APB1 additional enable register */ +#define RCU_AHB2RST REG32(RCU + 0x70U) /*!< AHB2 reset register */ +#define RCU_ADDAPB2RST REG32(RCU + 0x74U) /*!< APB2 additional reset register */ +#define RCU_ADDAPB1RST REG32(RCU + 0x78U) /*!< APB1 additional reset register */ +#define RCU_CFG2 REG32(RCU + 0x80U) /*!< configuration register 2 */ +#define RCU_PLLTCTL REG32(RCU + 0x90U) /*!< PLLT control register */ +#define RCU_PLLTINT REG32(RCU + 0x94U) /*!< PLLT interrupt register */ +#define RCU_PLLTCFG REG32(RCU + 0x98U) /*!< PLLT configuration register */ + +/* bits definitions */ +/* RCU_CTL */ +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ + +/* RCU_CFG0 */ +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ + +/* RCU_INT */ +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ +#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ +#define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ +#define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ +#define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHB1EN */ +#define RCU_AHB1EN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHB1EN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHB1EN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHB1EN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHB1EN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHB1EN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#define RCU_AHB1EN_SDIOEN BIT(10) /*!< SDIO clock enable */ +#define RCU_AHB1EN_USBFSEN BIT(12) /*!< USBFS clock enable */ +#define RCU_AHB1EN_ENETEN BIT(14) /*!< ENET clock enable */ +#define RCU_AHB1EN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ +#define RCU_AHB1EN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ +#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ +#define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ +#define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_LXTALDRI BITS(3,4) /*!< LXTAL drive capability */ +#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +/* RCU_AHB1RST */ +#define RCU_AHB1RST_USBFSRST BIT(12) /*!< USBFS reset */ +#define RCU_AHB1RST_ENETRST BIT(14) /*!< ENET reset */ + +/* RCU_CFG1 */ +#define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ + +/* RCU_AHB2EN */ +#define RCU_AHB2EN_DCIEN BIT(0) /*!< DCI clock enable */ +#define RCU_AHB2EN_CAUEN BIT(4) /*!< CAU clock enable */ +#define RCU_AHB2EN_HAUEN BIT(5) /*!< HAU clock enable */ +#define RCU_AHB2EN_TRNGEN BIT(6) /*!< TRNG clock enable */ + +/* RCU_ADDAPB2EN */ +#define RCU_ADDAPB2EN_USART5EN BIT(24) /*!< USART5 clock enable */ +#define RCU_ADDAPB2EN_TLIEN BIT(26) /*!< TLI clock enable */ +#define RCU_ADDAPB2EN_PHEN BIT(30) /*!< GPIO port H clock enable */ +#define RCU_ADDAPB2EN_PIEN BIT(31) /*!< GPIO port I clock enable */ + +/* RCU_ADDAPB1EN */ +#define RCU_ADDAPB1EN_I2C2EN BIT(23) /*!< I2C2 clock enable */ +#define RCU_ADDAPB1EN_UART6EN BIT(30) /*!< UART6 clock enable */ +#define RCU_ADDAPB1EN_UART7EN BIT(31) /*!< UART7 clock enable */ + +/* RCU_AHB2RST */ +#define RCU_AHB2RST_DCIRST BIT(0) /*!< DCI reset */ +#define RCU_AHB2RST_CAURST BIT(4) /*!< CAU reset */ +#define RCU_AHB2RST_HAURST BIT(5) /*!< HAU reset */ +#define RCU_AHB2RST_TRNGRST BIT(6) /*!< TRNG reset */ + +/* RCU_ADDAPB2RST */ +#define RCU_ADDAPB2RST_USART5RST BIT(24) /*!< USART5 reset */ +#define RCU_ADDAPB2RST_TLIRST BIT(26) /*!< TLI reset */ +#define RCU_ADDAPB2RST_PHRST BIT(30) /*!< GPIO port H reset */ +#define RCU_ADDAPB2RST_PIRST BIT(31) /*!< GPIO port I reset */ + +/* RCU_ADDAPB1RST */ +#define RCU_ADDAPB1RST_I2C2RST BIT(23) /*!< I2C2 reset */ +#define RCU_ADDAPB1RST_UART6RST BIT(30) /*!< UART6 reset */ +#define RCU_ADDAPB1RST_UART7RST BIT(31) /*!< UART7 reset */ + +/* RCU_CFG2 */ +#define RCU_CFG2_CKOUT0DIV BITS(0,5) /*!< CK_OUT0 divider */ +#define RCU_CFG2_CKOUT1DIV BITS(8,13) /*!< CK_OUT1 divider */ +#define RCU_CFG2_CKOUT1SEL BITS(16,19) /*!< CKOUT1 clock source selection */ + +/* RCU_PLLTCTL */ +#define RCU_PLLTCTL_PLLTEN BIT(28) /*!< PLLT enable */ +#define RCU_PLLTCTL_PLLTSTB BIT(29) /*!< PLLT clock stabilization flag */ + +/* RCU_PLLTINT */ +#define RCU_PLLTINT_PLLTSTBIF BIT(6) /*!< PLLT stabilization interrupt flag */ +#define RCU_PLLTINT_PLLTSTBIE BIT(14) /*!< PLLT stabilization interrupt enable */ +#define RCU_PLLTINT_PLLTSTBIC BIT(22) /*!< PLLT stabilization interrupt clear */ + +/* RCU_PLLTCFG */ +#define RCU_PLLTCFG_PLLTPSC BITS(0,5) /*!< PLLT prescaler selection */ +#define RCU_PLLTCFG_PLLTMF BITS(6,14) /*!< PLLT multiply factor for VCO */ +#define RCU_PLLTCFG_TLIPSC BITS(16,17) /*!< TLI prescaler selection */ +#define RCU_PLLTCFG_PLLTRPSC BITS(28,30) /*!< PLLTR prescaler selection */ +#define RCU_PLLTCFG_PLLTSEL BIT(31) /*!< PLLT clock source select */ + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHB1EN_REG_OFFSET 0x14U /*!< AHB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define AHB2EN_REG_OFFSET 0x60U /*!< AHB2 enable register offset */ +#define ADD_APB2EN_REG_OFFSET 0x64U /*!< APB2 additional enable register offset */ +#define ADD_APB1EN_REG_OFFSET 0x68U /*!< APB1 additional enable register offset */ + +/* peripherals reset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source / clock register offset */ +#define AHB1RST_REG_OFFSET 0x28U /*!< AHB1 reset register offset */ +#define AHB2RST_REG_OFFSET 0x70U /*!< AHB2 reset register offset */ +#define ADD_APB2RST_REG_OFFSET 0x74U /*!< APB2 additional reset register offset */ +#define ADD_APB1RST_REG_OFFSET 0x78U /*!< APB1 additional reset register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ +#define PLLTCTL_REG_OFFSET 0x90U /*!< PLLT control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< interrupt register offset */ +#define PLLTINT_REG_OFFSET 0x94U /*!< PLLT interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< configuration register 1 offset */ +#define CFG2_REG_OFFSET 0x80U /*!< configuration register 2 offset */ +#define PLLTCFG_REG_OFFSET 0x98U /*!< PLLT configuration register offset */ + +/* peripheral clock enable */ +typedef enum +{ + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 8U), /*!< EXMC clock */ + RCU_SDIO = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 10U), /*!< SDIO clock */ + RCU_USBFS = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 12U), /*!< USBFS clock */ + RCU_ENET = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 14U), /*!< ENET clock */ + RCU_ENETTX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 15U), /*!< ENETTX clock */ + RCU_ENETRX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 16U), /*!< ENETRX clock */ + + RCU_DCI = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 0U), /*!< DCI clock */ + RCU_CAU = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 4U), /*!< CAU clock */ + RCU_HAU = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 5U), /*!< HAU clock */ + RCU_TRNG = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 6U), /*!< TRNG clock */ + + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ + RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ + RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + + RCU_I2C2 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 23U), /*!< I2C2 clock */ + RCU_UART6 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 30U), /*!< UART6 clock */ + RCU_UART7 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 31U), /*!< UART7 clock */ + + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ + RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ + RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ + RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ + RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ + RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ + + RCU_USART5 = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 24U), /*!< USART5 clock */ + RCU_TLI = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 26U), /*!< TLI clock */ + RCU_GPIOH = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 30U), /*!< GPIOH clock */ + RCU_GPIOI = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 31U), /*!< GPIOI clock */ + +}rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum +{ + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 4U), /*!< FMC clock */ +}rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum +{ + /* AHB peripherals */ + RCU_USBFSRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 14U), /*!< ENET clock reset */ + + RCU_DCIRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 0U), /*!< DCI clock reset */ + RCU_CAURST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 4U), /*!< CAU clock reset */ + RCU_HAURST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 5U), /*!< HAU clock reset */ + RCU_TRNGRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 6U), /*!< TRNG clock reset */ + + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ + RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ + RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + + RCU_I2C2RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 23U), /*!< I2C2 clock reset */ + RCU_UART6RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 30U), /*!< UART6 clock reset */ + RCU_UART7RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 31U), /*!< UART7 clock reset */ + + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ + RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ + RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ + RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ + RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ + RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ + + RCU_USART5RST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 24U), /*!< USART5 clock reset */ + RCU_TLIRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 26U), /*!< TLI clock reset */ + RCU_GPIOHRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 30U), /*!< GPIOH clock reset */ + RCU_GPIOIRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 31U), /*!< GPIOI clock reset */ + +}rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum +{ + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ + + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + + RCU_FLAG_PLLTSTB = RCU_REGIDX_BIT(PLLTCTL_REG_OFFSET, 29U), /*!< PLLT stabilization flags */ + + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +}rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ + RCU_INT_FLAG_PLLTSTB = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 6U), /*!< PLLT stabilization interrupt flag */ +}rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ + RCU_INT_FLAG_PLLTSTB_CLR = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 22U), /*!< PLLT stabilization interrupt clear */ +}rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum +{ + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ + RCU_INT_PLLTSTB = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 14U), /*!< PLLT stabilization interrupt */ +}rcu_int_enum; + +/* oscillator types */ +typedef enum +{ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ + + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + + RCU_PLLT_CK = RCU_REGIDX_BIT(PLLTCTL_REG_OFFSET, 28U), /*!< PLLT */ + +}rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum +{ + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +}rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source selection */ +#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler selection */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL RCU_CFG0_PLLSEL /*!< HXTAL selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ + +/* USBFS/TRNG prescaler selection */ +#define CFG0_USBFSPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBFSPSC(0) /*!< USBFS/TRNG prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBFSPSC(1) /*!< USBFS/TRNG prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBFSPSC(2) /*!< USBFS/TRNG prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBFSPSC(3) /*!< USBFS/TRNG prescaler select CK_PLL/2 */ + +/* CKOUT0 Clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ + +/* LXTAL drive capability */ +#define BDCTL_LXTALDRI(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) +#define RCU_LXTAL_LOWDRI BDCTL_LXTALDRI(0) /*!< lower driving capability */ +#define RCU_LXTAL_MED_LOWDRI BDCTL_LXTALDRI(1) /*!< medium low driving capability */ +#define RCU_LXTAL_MED_HIGHDRI BDCTL_LXTALDRI(2) /*!< medium high driving capability */ +#define RCU_LXTAL_HIGHDRI BDCTL_LXTALDRI(3) /*!< higher driving capability */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock divided by 1 */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock divided by 1 */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ + +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_2 DSV_DSLPVS(0) /*!< core voltage is 1.2V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_1 DSV_DSLPVS(1) /*!< core voltage is 1.1V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(2) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(3) /*!< core voltage is 0.9V in deep-sleep mode */ + + +/* CKOUT0 division factor */ +#define CFG2_CKOUT0DIV(regval) (BITS(0,5) & ((uint32_t)(regval) << 0)) +#define RCU_CKOUT0_DIV1 CFG2_CKOUT0DIV(0) /*!< CK_OUT0 is divided by 1 */ +#define RCU_CKOUT0_DIV2 CFG2_CKOUT0DIV(1) /*!< CK_OUT0 is divided by 2 */ +#define RCU_CKOUT0_DIV3 CFG2_CKOUT0DIV(2) /*!< CK_OUT0 is divided by 3 */ +#define RCU_CKOUT0_DIV4 CFG2_CKOUT0DIV(3) /*!< CK_OUT0 is divided by 4 */ +#define RCU_CKOUT0_DIV5 CFG2_CKOUT0DIV(4) /*!< CK_OUT0 is divided by 5 */ +#define RCU_CKOUT0_DIV6 CFG2_CKOUT0DIV(5) /*!< CK_OUT0 is divided by 6 */ +#define RCU_CKOUT0_DIV7 CFG2_CKOUT0DIV(6) /*!< CK_OUT0 is divided by 7 */ +#define RCU_CKOUT0_DIV8 CFG2_CKOUT0DIV(7) /*!< CK_OUT0 is divided by 8 */ +#define RCU_CKOUT0_DIV9 CFG2_CKOUT0DIV(8) /*!< CK_OUT0 is divided by 9 */ +#define RCU_CKOUT0_DIV10 CFG2_CKOUT0DIV(9) /*!< CK_OUT0 is divided by 10 */ +#define RCU_CKOUT0_DIV11 CFG2_CKOUT0DIV(10) /*!< CK_OUT0 is divided by 11 */ +#define RCU_CKOUT0_DIV12 CFG2_CKOUT0DIV(11) /*!< CK_OUT0 is divided by 12 */ +#define RCU_CKOUT0_DIV13 CFG2_CKOUT0DIV(12) /*!< CK_OUT0 is divided by 13 */ +#define RCU_CKOUT0_DIV14 CFG2_CKOUT0DIV(13) /*!< CK_OUT0 is divided by 14 */ +#define RCU_CKOUT0_DIV15 CFG2_CKOUT0DIV(14) /*!< CK_OUT0 is divided by 15 */ +#define RCU_CKOUT0_DIV16 CFG2_CKOUT0DIV(15) /*!< CK_OUT0 is divided by 16 */ +#define RCU_CKOUT0_DIV17 CFG2_CKOUT0DIV(16) /*!< CK_OUT0 is divided by 17 */ +#define RCU_CKOUT0_DIV18 CFG2_CKOUT0DIV(17) /*!< CK_OUT0 is divided by 18 */ +#define RCU_CKOUT0_DIV19 CFG2_CKOUT0DIV(18) /*!< CK_OUT0 is divided by 19 */ +#define RCU_CKOUT0_DIV20 CFG2_CKOUT0DIV(19) /*!< CK_OUT0 is divided by 20 */ +#define RCU_CKOUT0_DIV21 CFG2_CKOUT0DIV(20) /*!< CK_OUT0 is divided by 21 */ +#define RCU_CKOUT0_DIV22 CFG2_CKOUT0DIV(21) /*!< CK_OUT0 is divided by 22 */ +#define RCU_CKOUT0_DIV23 CFG2_CKOUT0DIV(22) /*!< CK_OUT0 is divided by 23 */ +#define RCU_CKOUT0_DIV24 CFG2_CKOUT0DIV(23) /*!< CK_OUT0 is divided by 24 */ +#define RCU_CKOUT0_DIV25 CFG2_CKOUT0DIV(24) /*!< CK_OUT0 is divided by 25 */ +#define RCU_CKOUT0_DIV26 CFG2_CKOUT0DIV(25) /*!< CK_OUT0 is divided by 26 */ +#define RCU_CKOUT0_DIV27 CFG2_CKOUT0DIV(26) /*!< CK_OUT0 is divided by 27 */ +#define RCU_CKOUT0_DIV28 CFG2_CKOUT0DIV(27) /*!< CK_OUT0 is divided by 28 */ +#define RCU_CKOUT0_DIV29 CFG2_CKOUT0DIV(28) /*!< CK_OUT0 is divided by 29 */ +#define RCU_CKOUT0_DIV30 CFG2_CKOUT0DIV(29) /*!< CK_OUT0 is divided by 30 */ +#define RCU_CKOUT0_DIV31 CFG2_CKOUT0DIV(30) /*!< CK_OUT0 is divided by 31 */ +#define RCU_CKOUT0_DIV32 CFG2_CKOUT0DIV(31) /*!< CK_OUT0 is divided by 32 */ +#define RCU_CKOUT0_DIV33 CFG2_CKOUT0DIV(32) /*!< CK_OUT0 is divided by 33 */ +#define RCU_CKOUT0_DIV34 CFG2_CKOUT0DIV(33) /*!< CK_OUT0 is divided by 34 */ +#define RCU_CKOUT0_DIV35 CFG2_CKOUT0DIV(34) /*!< CK_OUT0 is divided by 35 */ +#define RCU_CKOUT0_DIV36 CFG2_CKOUT0DIV(35) /*!< CK_OUT0 is divided by 36 */ +#define RCU_CKOUT0_DIV37 CFG2_CKOUT0DIV(36) /*!< CK_OUT0 is divided by 37 */ +#define RCU_CKOUT0_DIV38 CFG2_CKOUT0DIV(37) /*!< CK_OUT0 is divided by 38 */ +#define RCU_CKOUT0_DIV39 CFG2_CKOUT0DIV(38) /*!< CK_OUT0 is divided by 39 */ +#define RCU_CKOUT0_DIV40 CFG2_CKOUT0DIV(39) /*!< CK_OUT0 is divided by 40 */ +#define RCU_CKOUT0_DIV41 CFG2_CKOUT0DIV(40) /*!< CK_OUT0 is divided by 41 */ +#define RCU_CKOUT0_DIV42 CFG2_CKOUT0DIV(41) /*!< CK_OUT0 is divided by 42 */ +#define RCU_CKOUT0_DIV43 CFG2_CKOUT0DIV(42) /*!< CK_OUT0 is divided by 43 */ +#define RCU_CKOUT0_DIV44 CFG2_CKOUT0DIV(43) /*!< CK_OUT0 is divided by 44 */ +#define RCU_CKOUT0_DIV45 CFG2_CKOUT0DIV(44) /*!< CK_OUT0 is divided by 45 */ +#define RCU_CKOUT0_DIV46 CFG2_CKOUT0DIV(45) /*!< CK_OUT0 is divided by 46 */ +#define RCU_CKOUT0_DIV47 CFG2_CKOUT0DIV(46) /*!< CK_OUT0 is divided by 47 */ +#define RCU_CKOUT0_DIV48 CFG2_CKOUT0DIV(47) /*!< CK_OUT0 is divided by 48 */ +#define RCU_CKOUT0_DIV49 CFG2_CKOUT0DIV(48) /*!< CK_OUT0 is divided by 49 */ +#define RCU_CKOUT0_DIV50 CFG2_CKOUT0DIV(49) /*!< CK_OUT0 is divided by 20 */ +#define RCU_CKOUT0_DIV51 CFG2_CKOUT0DIV(40) /*!< CK_OUT0 is divided by 51 */ +#define RCU_CKOUT0_DIV52 CFG2_CKOUT0DIV(51) /*!< CK_OUT0 is divided by 52 */ +#define RCU_CKOUT0_DIV53 CFG2_CKOUT0DIV(52) /*!< CK_OUT0 is divided by 53 */ +#define RCU_CKOUT0_DIV54 CFG2_CKOUT0DIV(53) /*!< CK_OUT0 is divided by 54 */ +#define RCU_CKOUT0_DIV55 CFG2_CKOUT0DIV(54) /*!< CK_OUT0 is divided by 55 */ +#define RCU_CKOUT0_DIV56 CFG2_CKOUT0DIV(55) /*!< CK_OUT0 is divided by 56 */ +#define RCU_CKOUT0_DIV57 CFG2_CKOUT0DIV(56) /*!< CK_OUT0 is divided by 57 */ +#define RCU_CKOUT0_DIV58 CFG2_CKOUT0DIV(57) /*!< CK_OUT0 is divided by 58 */ +#define RCU_CKOUT0_DIV59 CFG2_CKOUT0DIV(58) /*!< CK_OUT0 is divided by 59 */ +#define RCU_CKOUT0_DIV60 CFG2_CKOUT0DIV(59) /*!< CK_OUT0 is divided by 60 */ +#define RCU_CKOUT0_DIV61 CFG2_CKOUT0DIV(60) /*!< CK_OUT0 is divided by 61 */ +#define RCU_CKOUT0_DIV62 CFG2_CKOUT0DIV(61) /*!< CK_OUT0 is divided by 62 */ +#define RCU_CKOUT0_DIV63 CFG2_CKOUT0DIV(62) /*!< CK_OUT0 is divided by 63 */ +#define RCU_CKOUT0_DIV64 CFG2_CKOUT0DIV(63) /*!< CK_OUT0 is divided by 64 */ + +/* CKOUT1 division factor */ +#define CFG2_CKOUT1DIV(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) +#define RCU_CKOUT1_DIV1 CFG2_CKOUT1DIV(0) /*!< CK_OUT1 is divided by 1 */ +#define RCU_CKOUT1_DIV2 CFG2_CKOUT1DIV(1) /*!< CK_OUT1 is divided by 2 */ +#define RCU_CKOUT1_DIV3 CFG2_CKOUT1DIV(2) /*!< CK_OUT1 is divided by 3 */ +#define RCU_CKOUT1_DIV4 CFG2_CKOUT1DIV(3) /*!< CK_OUT1 is divided by 4 */ +#define RCU_CKOUT1_DIV5 CFG2_CKOUT1DIV(4) /*!< CK_OUT1 is divided by 5 */ +#define RCU_CKOUT1_DIV6 CFG2_CKOUT1DIV(5) /*!< CK_OUT1 is divided by 6 */ +#define RCU_CKOUT1_DIV7 CFG2_CKOUT1DIV(6) /*!< CK_OUT1 is divided by 7 */ +#define RCU_CKOUT1_DIV8 CFG2_CKOUT1DIV(7) /*!< CK_OUT1 is divided by 8 */ +#define RCU_CKOUT1_DIV9 CFG2_CKOUT1DIV(8) /*!< CK_OUT1 is divided by 9 */ +#define RCU_CKOUT1_DIV10 CFG2_CKOUT1DIV(9) /*!< CK_OUT1 is divided by 10 */ +#define RCU_CKOUT1_DIV11 CFG2_CKOUT1DIV(10) /*!< CK_OUT1 is divided by 11 */ +#define RCU_CKOUT1_DIV12 CFG2_CKOUT1DIV(11) /*!< CK_OUT1 is divided by 12 */ +#define RCU_CKOUT1_DIV13 CFG2_CKOUT1DIV(12) /*!< CK_OUT1 is divided by 13 */ +#define RCU_CKOUT1_DIV14 CFG2_CKOUT1DIV(13) /*!< CK_OUT1 is divided by 14 */ +#define RCU_CKOUT1_DIV15 CFG2_CKOUT1DIV(14) /*!< CK_OUT1 is divided by 15 */ +#define RCU_CKOUT1_DIV16 CFG2_CKOUT1DIV(15) /*!< CK_OUT1 is divided by 16 */ +#define RCU_CKOUT1_DIV17 CFG2_CKOUT1DIV(16) /*!< CK_OUT1 is divided by 17 */ +#define RCU_CKOUT1_DIV18 CFG2_CKOUT1DIV(17) /*!< CK_OUT1 is divided by 18 */ +#define RCU_CKOUT1_DIV19 CFG2_CKOUT1DIV(18) /*!< CK_OUT1 is divided by 19 */ +#define RCU_CKOUT1_DIV20 CFG2_CKOUT1DIV(19) /*!< CK_OUT1 is divided by 20 */ +#define RCU_CKOUT1_DIV21 CFG2_CKOUT1DIV(20) /*!< CK_OUT1 is divided by 21 */ +#define RCU_CKOUT1_DIV22 CFG2_CKOUT1DIV(21) /*!< CK_OUT1 is divided by 22 */ +#define RCU_CKOUT1_DIV23 CFG2_CKOUT1DIV(22) /*!< CK_OUT1 is divided by 23 */ +#define RCU_CKOUT1_DIV24 CFG2_CKOUT1DIV(23) /*!< CK_OUT1 is divided by 24 */ +#define RCU_CKOUT1_DIV25 CFG2_CKOUT1DIV(24) /*!< CK_OUT1 is divided by 25 */ +#define RCU_CKOUT1_DIV26 CFG2_CKOUT1DIV(25) /*!< CK_OUT1 is divided by 26 */ +#define RCU_CKOUT1_DIV27 CFG2_CKOUT1DIV(26) /*!< CK_OUT1 is divided by 27 */ +#define RCU_CKOUT1_DIV28 CFG2_CKOUT1DIV(27) /*!< CK_OUT1 is divided by 28 */ +#define RCU_CKOUT1_DIV29 CFG2_CKOUT1DIV(28) /*!< CK_OUT1 is divided by 29 */ +#define RCU_CKOUT1_DIV30 CFG2_CKOUT1DIV(29) /*!< CK_OUT1 is divided by 30 */ +#define RCU_CKOUT1_DIV31 CFG2_CKOUT1DIV(30) /*!< CK_OUT1 is divided by 31 */ +#define RCU_CKOUT1_DIV32 CFG2_CKOUT1DIV(31) /*!< CK_OUT1 is divided by 32 */ +#define RCU_CKOUT1_DIV33 CFG2_CKOUT1DIV(32) /*!< CK_OUT1 is divided by 33 */ +#define RCU_CKOUT1_DIV34 CFG2_CKOUT1DIV(33) /*!< CK_OUT1 is divided by 34 */ +#define RCU_CKOUT1_DIV35 CFG2_CKOUT1DIV(34) /*!< CK_OUT1 is divided by 35 */ +#define RCU_CKOUT1_DIV36 CFG2_CKOUT1DIV(35) /*!< CK_OUT1 is divided by 36 */ +#define RCU_CKOUT1_DIV37 CFG2_CKOUT1DIV(36) /*!< CK_OUT1 is divided by 37 */ +#define RCU_CKOUT1_DIV38 CFG2_CKOUT1DIV(37) /*!< CK_OUT1 is divided by 38 */ +#define RCU_CKOUT1_DIV39 CFG2_CKOUT1DIV(38) /*!< CK_OUT1 is divided by 39 */ +#define RCU_CKOUT1_DIV40 CFG2_CKOUT1DIV(39) /*!< CK_OUT1 is divided by 40 */ +#define RCU_CKOUT1_DIV41 CFG2_CKOUT1DIV(40) /*!< CK_OUT1 is divided by 41 */ +#define RCU_CKOUT1_DIV42 CFG2_CKOUT1DIV(41) /*!< CK_OUT1 is divided by 42 */ +#define RCU_CKOUT1_DIV43 CFG2_CKOUT1DIV(42) /*!< CK_OUT1 is divided by 43 */ +#define RCU_CKOUT1_DIV44 CFG2_CKOUT1DIV(43) /*!< CK_OUT1 is divided by 44 */ +#define RCU_CKOUT1_DIV45 CFG2_CKOUT1DIV(44) /*!< CK_OUT1 is divided by 45 */ +#define RCU_CKOUT1_DIV46 CFG2_CKOUT1DIV(45) /*!< CK_OUT1 is divided by 46 */ +#define RCU_CKOUT1_DIV47 CFG2_CKOUT1DIV(46) /*!< CK_OUT1 is divided by 47 */ +#define RCU_CKOUT1_DIV48 CFG2_CKOUT1DIV(47) /*!< CK_OUT1 is divided by 48 */ +#define RCU_CKOUT1_DIV49 CFG2_CKOUT1DIV(48) /*!< CK_OUT1 is divided by 49 */ +#define RCU_CKOUT1_DIV50 CFG2_CKOUT1DIV(49) /*!< CK_OUT1 is divided by 20 */ +#define RCU_CKOUT1_DIV51 CFG2_CKOUT1DIV(40) /*!< CK_OUT1 is divided by 51 */ +#define RCU_CKOUT1_DIV52 CFG2_CKOUT1DIV(51) /*!< CK_OUT1 is divided by 52 */ +#define RCU_CKOUT1_DIV53 CFG2_CKOUT1DIV(52) /*!< CK_OUT1 is divided by 53 */ +#define RCU_CKOUT1_DIV54 CFG2_CKOUT1DIV(53) /*!< CK_OUT1 is divided by 54 */ +#define RCU_CKOUT1_DIV55 CFG2_CKOUT1DIV(54) /*!< CK_OUT1 is divided by 55 */ +#define RCU_CKOUT1_DIV56 CFG2_CKOUT1DIV(55) /*!< CK_OUT1 is divided by 56 */ +#define RCU_CKOUT1_DIV57 CFG2_CKOUT1DIV(56) /*!< CK_OUT1 is divided by 57 */ +#define RCU_CKOUT1_DIV58 CFG2_CKOUT1DIV(57) /*!< CK_OUT1 is divided by 58 */ +#define RCU_CKOUT1_DIV59 CFG2_CKOUT1DIV(58) /*!< CK_OUT1 is divided by 59 */ +#define RCU_CKOUT1_DIV60 CFG2_CKOUT1DIV(59) /*!< CK_OUT1 is divided by 60 */ +#define RCU_CKOUT1_DIV61 CFG2_CKOUT1DIV(60) /*!< CK_OUT1 is divided by 61 */ +#define RCU_CKOUT1_DIV62 CFG2_CKOUT1DIV(61) /*!< CK_OUT1 is divided by 62 */ +#define RCU_CKOUT1_DIV63 CFG2_CKOUT1DIV(62) /*!< CK_OUT1 is divided by 63 */ +#define RCU_CKOUT1_DIV64 CFG2_CKOUT1DIV(63) /*!< CK_OUT1 is divided by 64 */ + +/* CKOUT1 Clock source selection */ +#define CFG2_CKOUT1SEL(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) +#define RCU_CKOUT1SRC_NONE CFG2_CKOUT1SEL(0) /*!< no clock selected */ +#define RCU_CKOUT1SRC_CKSYS CFG2_CKOUT1SEL(4) /*!< system clock selected */ +#define RCU_CKOUT1SRC_IRC8M CFG2_CKOUT1SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT1SRC_HXTAL CFG2_CKOUT1SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT1SRC_CKPLL_DIV2 CFG2_CKOUT1SEL(7) /*!< CK_PLL/2 clock selected */ +#define RCU_CKOUT1SRC_CKPLL1 CFG2_CKOUT1SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT1SRC_CKPLL2_DIV2 CFG2_CKOUT1SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT1SRC_EXT1 CFG2_CKOUT1SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT1SRC_CKPLL2 CFG2_CKOUT1SEL(11) /*!< CK_PLL2 clock selected */ + +/* PLLT division factor */ +#define PLLTCFG_PLLTPSC(regval) (BITS(0,5) & ((uint32_t)(regval) << 0)) + +/* PLLT clock multiplication factor for VCO */ +#define PLLTCFG_PLLTMF(regval) (BITS(6,14) & ((uint32_t)(regval) << 6)) + +/* TLI prescaler select */ +#define PLLTCFG_TLIPSC(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) +#define RCU_CKTLI_CKPLLTR_DIV2 PLLTCFG_TLIPSC(0) /*!< TLI prescaler select CK_PLLTR/2 */ +#define RCU_CKTLI_CKPLLTR_DIV4 PLLTCFG_TLIPSC(1) /*!< TLI prescaler select CK_PLLTR/4 */ +#define RCU_CKTLI_CKPLLTR_DIV8 PLLTCFG_TLIPSC(2) /*!< TLI prescaler select CK_PLLTR/8 */ +#define RCU_CKTLI_CKPLLTR_DIV16 PLLTCFG_TLIPSC(3) /*!< TLI prescaler select CK_PLLTR/16 */ + +/* PLLTR division factor */ +#define PLLTCFG_PLLTRPSC(regval) (BITS(28,30) & ((uint32_t)(regval) << 28)) + +/* PLLT clock source selection */ +#define RCU_PLLTSRC_IRC8M ((uint32_t)0x00000000U) /*!< IRC8M selected as source clock of PLLT */ +#define RCU_PLLTSRC_HXTAL RCU_PLLTCFG_PLLTSEL /*!< HXTAL selected as source clock of PLLT */ + +/* function declarations */ +/* initialization, peripheral clock enable/disable functions */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* clock configuration functions */ +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); + +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div); +/* configure the CK_OUT1 clock source and divider */ +void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div); + +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); + +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); + +/* peripheral clock configuration functions */ +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBFS/TRNG prescaler factor */ +void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); + +/* configure the PLLT clock selection */ +void rcu_pllt_config(uint32_t pllt_src); +/* Configure the PLLT clock multiplication and division factors */ +ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppltr_psc); +/* configure the TLI prescaler factor */ +void rcu_tli_clock_config(uint32_t tli_psc); + +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum stab_int); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum stab_int); + +/* configure the LXTAL drive capability */ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval); + +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32F20X_RCU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h new file mode 100644 index 0000000000..14e51f6abf --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h @@ -0,0 +1,151 @@ +/*! + \file gd32f20x_rtc.h + \brief definitions for the RTC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_RTC_H +#define GD32F20X_RTC_H + +#include "gd32f20x.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSCH */ +#define RTC_PSCH_PSC BITS(0,3) /*!< prescaler high value */ + +/* RTC_PSCL */ +#define RTC_PSCL_PSC BITS(0,15) /*!< prescaler low value */ + +/* RTC_DIVH */ +#define RTC_DIVH_DIV BITS(0,3) /*!< divider high value */ + +/* RTC_DIVL */ +#define RTC_DIVL_DIV BITS(0,15) /*!< divider low value */ + +/* RTC_CNTH */ +#define RTC_CNTH_CNT BITS(0,15) /*!< counter high value */ + +/* RTC_CNTL */ +#define RTC_CNTL_CNT BITS(0,15) /*!< counter low value */ + +/* RTC_ALRMH */ +#define RTC_ALRMH_ALRM BITS(0,15) /*!< alarm high value */ + +/* RTC_ALRML */ +#define RTC_ALRML_ALRM BITS(0,15) /*!< alarm low value */ + +/* constants definitions */ +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC interrupt flag definitions */ +#define RTC_INT_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_INT_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_INT_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* initialization functions */ +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); + +/* operation functions */ +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* flag & interrupt functions */ +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); +/* get RTC interrupt flag status */ +FlagStatus rtc_interrupt_flag_get(uint32_t flag); +/* clear RTC interrupt flag status */ +void rtc_interrupt_flag_clear(uint32_t flag); +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +#endif /* GD32F20X_RTC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h new file mode 100644 index 0000000000..fd885a3ce8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h @@ -0,0 +1,433 @@ +/*! + \file gd32f20x_sdio.h + \brief definitions for the SDIO + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_SDIO_H +#define GD32F20X_SDIO_H + +#include "gd32f20x.h" + +/* SDIO definitions */ +#define SDIO SDIO_BASE + +/* registers definitions */ +#define SDIO_PWRCTL REG32(SDIO + 0x00U) /*!< SDIO power control register */ +#define SDIO_CLKCTL REG32(SDIO + 0x04U) /*!< SDIO clock control register */ +#define SDIO_CMDAGMT REG32(SDIO + 0x08U) /*!< SDIO command argument register */ +#define SDIO_CMDCTL REG32(SDIO + 0x0CU) /*!< SDIO command control register */ +#define SDIO_RSPCMDIDX REG32(SDIO + 0x10U) /*!< SDIO command index response register */ +#define SDIO_RESP0 REG32(SDIO + 0x14U) /*!< SDIO response register 0 */ +#define SDIO_RESP1 REG32(SDIO + 0x18U) /*!< SDIO response register 1 */ +#define SDIO_RESP2 REG32(SDIO + 0x1CU) /*!< SDIO response register 2 */ +#define SDIO_RESP3 REG32(SDIO + 0x20U) /*!< SDIO response register 3 */ +#define SDIO_DATATO REG32(SDIO + 0x24U) /*!< SDIO data timeout register */ +#define SDIO_DATALEN REG32(SDIO + 0x28U) /*!< SDIO data length register */ +#define SDIO_DATACTL REG32(SDIO + 0x2CU) /*!< SDIO data control register */ +#define SDIO_DATACNT REG32(SDIO + 0x30U) /*!< SDIO data counter register */ +#define SDIO_STAT REG32(SDIO + 0x34U) /*!< SDIO status register */ +#define SDIO_INTC REG32(SDIO + 0x38U) /*!< SDIO interrupt clear register */ +#define SDIO_INTEN REG32(SDIO + 0x3CU) /*!< SDIO interrupt enable register */ +#define SDIO_FIFOCNT REG32(SDIO + 0x48U) /*!< SDIO FIFO counter register */ +#define SDIO_FIFO REG32(SDIO + 0x80U) /*!< SDIO FIFO data register */ + +/* bits definitions */ +/* SDIO_PWRCTL */ +#define SDIO_PWRCTL_PWRCTL BITS(0,1) /*!< SDIO power control bits */ + +/* SDIO_CLKCTL */ +#define SDIO_CLKCTL_DIV BITS(0,7) /*!< clock division */ +#define SDIO_CLKCTL_CLKEN BIT(8) /*!< SDIO_CLK clock output enable bit */ +#define SDIO_CLKCTL_CLKPWRSAV BIT(9) /*!< SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLKCTL_CLKBYP BIT(10) /*!< clock bypass enable bit */ +#define SDIO_CLKCTL_BUSMODE BITS(11,12) /*!< SDIO card bus mode control bit */ +#define SDIO_CLKCTL_CLKEDGE BIT(13) /*!< SDIO_CLK clock edge selection bit */ +#define SDIO_CLKCTL_HWCLKEN BIT(14) /*!< hardware clock control enable bit */ +#define SDIO_CLKCTL_DIV8 BIT(31) /*!< MSB of clock division */ + +/* SDIO_CMDAGMT */ +#define SDIO_CMDAGMT_CMDAGMT BITS(0,31) /*!< SDIO card command argument */ + +/* SDIO_CMDCTL */ +#define SDIO_CMDCTL_CMDIDX BITS(0,5) /*!< command index */ +#define SDIO_CMDCTL_CMDRESP BITS(6,7) /*!< command response type bits */ +#define SDIO_CMDCTL_INTWAIT BIT(8) /*!< interrupt wait instead of timeout */ +#define SDIO_CMDCTL_WAITDEND BIT(9) /*!< wait for ends of data transfer */ +#define SDIO_CMDCTL_CSMEN BIT(10) /*!< command state machine(CSM) enable bit */ +#define SDIO_CMDCTL_SUSPEND BIT(11) /*!< SD I/O suspend command(SD I/O only) */ +#define SDIO_CMDCTL_ENCMDC BIT(12) /*!< CMD completion signal enabled (CE-ATA only) */ +#define SDIO_CMDCTL_NINTEN BIT(13) /*!< no CE-ATA interrupt (CE-ATA only) */ +#define SDIO_CMDCTL_ATAEN BIT(14) /*!< CE-ATA command enable(CE-ATA only) */ + +/* SDIO_DATATO */ +#define SDIO_DATATO_DATATO BITS(0,31) /*!< data timeout period */ + +/* SDIO_DATALEN */ +#define SDIO_DATALEN_DATALEN BITS(0,24) /*!< data transfer length */ + +/* SDIO_DATACTL */ +#define SDIO_DATACTL_DATAEN BIT(0) /*!< data transfer enabled bit */ +#define SDIO_DATACTL_DATADIR BIT(1) /*!< data transfer direction */ +#define SDIO_DATACTL_TRANSMOD BIT(2) /*!< data transfer mode */ +#define SDIO_DATACTL_DMAEN BIT(3) /*!< DMA enable bit */ +#define SDIO_DATACTL_BLKSZ BITS(4,7) /*!< data block size */ +#define SDIO_DATACTL_RWEN BIT(8) /*!< read wait mode enabled(SD I/O only) */ +#define SDIO_DATACTL_RWSTOP BIT(9) /*!< read wait stop(SD I/O only) */ +#define SDIO_DATACTL_RWTYPE BIT(10) /*!< read wait type(SD I/O only) */ +#define SDIO_DATACTL_IOEN BIT(11) /*!< SD I/O specific function enable(SD I/O only) */ + +/* SDIO_STAT */ +#define SDIO_STAT_CCRCERR BIT(0) /*!< command response received (CRC check failed) */ +#define SDIO_STAT_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) */ +#define SDIO_STAT_CMDTMOUT BIT(2) /*!< command response timeout */ +#define SDIO_STAT_DTTMOUT BIT(3) /*!< data timeout */ +#define SDIO_STAT_TXURE BIT(4) /*!< transmit FIFO underrun error occurs */ +#define SDIO_STAT_RXORE BIT(5) /*!< received FIFO overrun error occurs */ +#define SDIO_STAT_CMDRECV BIT(6) /*!< command response received (CRC check passed) */ +#define SDIO_STAT_CMDSEND BIT(7) /*!< command sent (no response required) */ +#define SDIO_STAT_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) */ +#define SDIO_STAT_STBITE BIT(9) /*!< start bit error in the bus */ +#define SDIO_STAT_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) */ +#define SDIO_STAT_CMDRUN BIT(11) /*!< command transmission in progress */ +#define SDIO_STAT_TXRUN BIT(12) /*!< data transmission in progress */ +#define SDIO_STAT_RXRUN BIT(13) /*!< data reception in progress */ +#define SDIO_STAT_TFH BIT(14) /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */ +#define SDIO_STAT_RFH BIT(15) /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */ +#define SDIO_STAT_TFF BIT(16) /*!< transmit FIFO is full */ +#define SDIO_STAT_RFF BIT(17) /*!< receive FIFO is full */ +#define SDIO_STAT_TFE BIT(18) /*!< transmit FIFO is empty */ +#define SDIO_STAT_RFE BIT(19) /*!< receive FIFO is empty */ +#define SDIO_STAT_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO */ +#define SDIO_STAT_RXDTVAL BIT(21) /*!< data is valid in receive FIFO */ +#define SDIO_STAT_SDIOINT BIT(22) /*!< SD I/O interrupt received */ +#define SDIO_STAT_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) */ + +/* SDIO_INTC */ +#define SDIO_INTC_CCRCERRC BIT(0) /*!< CCRCERR flag clear bit */ +#define SDIO_INTC_DTCRCERRC BIT(1) /*!< DTCRCERR flag clear bit */ +#define SDIO_INTC_CMDTMOUTC BIT(2) /*!< CMDTMOUT flag clear bit */ +#define SDIO_INTC_DTTMOUTC BIT(3) /*!< DTTMOUT flag clear bit */ +#define SDIO_INTC_TXUREC BIT(4) /*!< TXURE flag clear bit */ +#define SDIO_INTC_RXOREC BIT(5) /*!< RXORE flag clear bit */ +#define SDIO_INTC_CMDRECVC BIT(6) /*!< CMDRECV flag clear bit */ +#define SDIO_INTC_CMDSENDC BIT(7) /*!< CMDSEND flag clear bit */ +#define SDIO_INTC_DTENDC BIT(8) /*!< DTEND flag clear bit */ +#define SDIO_INTC_STBITEC BIT(9) /*!< STBITE flag clear bit */ +#define SDIO_INTC_DTBLKENDC BIT(10) /*!< DTBLKEND flag clear bit */ +#define SDIO_INTC_SDIOINTC BIT(22) /*!< SDIOINT flag clear bit */ +#define SDIO_INTC_ATAENDC BIT(23) /*!< ATAEND flag clear bit */ + +/* SDIO_INTEN */ +#define SDIO_INTEN_CCRCERRIE BIT(0) /*!< command response CRC fail interrupt enable */ +#define SDIO_INTEN_DTCRCERRIE BIT(1) /*!< data CRC fail interrupt enable */ +#define SDIO_INTEN_CMDTMOUTIE BIT(2) /*!< command response timeout interrupt enable */ +#define SDIO_INTEN_DTTMOUTIE BIT(3) /*!< data timeout interrupt enable */ +#define SDIO_INTEN_TXUREIE BIT(4) /*!< transmit FIFO underrun error interrupt enable */ +#define SDIO_INTEN_RXOREIE BIT(5) /*!< received FIFO overrun error interrupt enable */ +#define SDIO_INTEN_CMDRECVIE BIT(6) /*!< command response received interrupt enable */ +#define SDIO_INTEN_CMDSENDIE BIT(7) /*!< command sent interrupt enable */ +#define SDIO_INTEN_DTENDIE BIT(8) /*!< data end interrupt enable */ +#define SDIO_INTEN_STBITEIE BIT(9) /*!< start bit error interrupt enable */ +#define SDIO_INTEN_DTBLKENDIE BIT(10) /*!< data block end interrupt enable */ +#define SDIO_INTEN_CMDRUNIE BIT(11) /*!< command transmission interrupt enable */ +#define SDIO_INTEN_TXRUNIE BIT(12) /*!< data transmission interrupt enable */ +#define SDIO_INTEN_RXRUNIE BIT(13) /*!< data reception interrupt enable */ +#define SDIO_INTEN_TFHIE BIT(14) /*!< transmit FIFO half empty interrupt enable */ +#define SDIO_INTEN_RFHIE BIT(15) /*!< receive FIFO half full interrupt enable */ +#define SDIO_INTEN_TFFIE BIT(16) /*!< transmit FIFO full interrupt enable */ +#define SDIO_INTEN_RFFIE BIT(17) /*!< receive FIFO full interrupt enable */ +#define SDIO_INTEN_TFEIE BIT(18) /*!< transmit FIFO empty interrupt enable */ +#define SDIO_INTEN_RFEIE BIT(19) /*!< receive FIFO empty interrupt enable */ +#define SDIO_INTEN_TXDTVALIE BIT(20) /*!< data valid in transmit FIFO interrupt enable */ +#define SDIO_INTEN_RXDTVALIE BIT(21) /*!< data valid in receive FIFO interrupt enable */ +#define SDIO_INTEN_SDIOINTIE BIT(22) /*!< SD I/O interrupt received interrupt enable */ +#define SDIO_INTEN_ATAENDIE BIT(23) /*!< CE-ATA command completion signal received interrupt enable */ + +/* SDIO_FIFO */ +#define SDIO_FIFO_FIFODT BITS(0,31) /*!< receive FIFO data or transmit FIFO data */ + +/* constants definitions */ +/* SDIO flags */ +#define SDIO_FLAG_CCRCERR BIT(0) /*!< command response received (CRC check failed) flag */ +#define SDIO_FLAG_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) flag */ +#define SDIO_FLAG_CMDTMOUT BIT(2) /*!< command response timeout flag */ +#define SDIO_FLAG_DTTMOUT BIT(3) /*!< data timeout flag */ +#define SDIO_FLAG_TXURE BIT(4) /*!< transmit FIFO underrun error occurs flag */ +#define SDIO_FLAG_RXORE BIT(5) /*!< received FIFO overrun error occurs flag */ +#define SDIO_FLAG_CMDRECV BIT(6) /*!< command response received (CRC check passed) flag */ +#define SDIO_FLAG_CMDSEND BIT(7) /*!< command sent (no response required) flag */ +#define SDIO_FLAG_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) flag */ +#define SDIO_FLAG_STBITE BIT(9) /*!< start bit error in the bus flag */ +#define SDIO_FLAG_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) flag */ +#define SDIO_FLAG_CMDRUN BIT(11) /*!< command transmission in progress flag */ +#define SDIO_FLAG_TXRUN BIT(12) /*!< data transmission in progress flag */ +#define SDIO_FLAG_RXRUN BIT(13) /*!< data reception in progress flag */ +#define SDIO_FLAG_TFH BIT(14) /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */ +#define SDIO_FLAG_RFH BIT(15) /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */ +#define SDIO_FLAG_TFF BIT(16) /*!< transmit FIFO is full flag */ +#define SDIO_FLAG_RFF BIT(17) /*!< receive FIFO is full flag */ +#define SDIO_FLAG_TFE BIT(18) /*!< transmit FIFO is empty flag */ +#define SDIO_FLAG_RFE BIT(19) /*!< receive FIFO is empty flag */ +#define SDIO_FLAG_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO flag */ +#define SDIO_FLAG_RXDTVAL BIT(21) /*!< data is valid in receive FIFO flag */ +#define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ +#define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ + +/* SDIO interrupt enable or disable */ +#define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO power control */ +#define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ +#define SDIO_POWER_ON PWRCTL_PWRCTL(3) /*!< SDIO power on */ + +/* SDIO card bus mode control */ +#define CLKCTL_BUSMODE(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) +#define SDIO_BUSMODE_1BIT CLKCTL_BUSMODE(0) /*!< 1-bit SDIO card bus mode */ +#define SDIO_BUSMODE_4BIT CLKCTL_BUSMODE(1) /*!< 4-bit SDIO card bus mode */ +#define SDIO_BUSMODE_8BIT CLKCTL_BUSMODE(2) /*!< 8-bit SDIO card bus mode */ + +/* SDIO_CLK clock edge selection */ +#define SDIO_SDIOCLKEDGE_RISING ((uint32_t)0x00000000U)/*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */ +#define SDIO_SDIOCLKEDGE_FALLING SDIO_CLKCTL_CLKEDGE /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */ + +/* clock bypass enable or disable */ +#define SDIO_CLOCKBYPASS_DISABLE ((uint32_t)0x00000000U)/*!< no bypass */ +#define SDIO_CLOCKBYPASS_ENABLE SDIO_CLKCTL_CLKBYP /*!< clock bypass */ + +/* SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLOCKPWRSAVE_DISABLE ((uint32_t)0x00000000U)/*!< SDIO_CLK clock is always on */ +#define SDIO_CLOCKPWRSAVE_ENABLE SDIO_CLKCTL_CLKPWRSAV /*!< SDIO_CLK closed when bus is idle */ + +/* SDIO command response type */ +#define CMDCTL_CMDRESP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define SDIO_RESPONSETYPE_NO CMDCTL_CMDRESP(0) /*!< no response */ +#define SDIO_RESPONSETYPE_SHORT CMDCTL_CMDRESP(1) /*!< short response */ +#define SDIO_RESPONSETYPE_LONG CMDCTL_CMDRESP(3) /*!< long response */ + +/* command state machine wait type */ +#define SDIO_WAITTYPE_NO ((uint32_t)0x00000000U)/*!< not wait interrupt */ +#define SDIO_WAITTYPE_INTERRUPT SDIO_CMDCTL_INTWAIT /*!< wait interrupt */ +#define SDIO_WAITTYPE_DATAEND SDIO_CMDCTL_WAITDEND /*!< wait the end of data transfer */ + +#define SDIO_RESPONSE0 ((uint32_t)0x00000000U)/*!< card response[31:0]/card response[127:96] */ +#define SDIO_RESPONSE1 ((uint32_t)0x00000001U)/*!< card response[95:64] */ +#define SDIO_RESPONSE2 ((uint32_t)0x00000002U)/*!< card response[63:32] */ +#define SDIO_RESPONSE3 ((uint32_t)0x00000003U)/*!< card response[31:1], plus bit 0 */ + +/* SDIO data block size */ +#define DATACTL_BLKSZ(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define SDIO_DATABLOCKSIZE_1BYTE DATACTL_BLKSZ(0) /*!< block size = 1 byte */ +#define SDIO_DATABLOCKSIZE_2BYTES DATACTL_BLKSZ(1) /*!< block size = 2 bytes */ +#define SDIO_DATABLOCKSIZE_4BYTES DATACTL_BLKSZ(2) /*!< block size = 4 bytes */ +#define SDIO_DATABLOCKSIZE_8BYTES DATACTL_BLKSZ(3) /*!< block size = 8 bytes */ +#define SDIO_DATABLOCKSIZE_16BYTES DATACTL_BLKSZ(4) /*!< block size = 16 bytes */ +#define SDIO_DATABLOCKSIZE_32BYTES DATACTL_BLKSZ(5) /*!< block size = 32 bytes */ +#define SDIO_DATABLOCKSIZE_64BYTES DATACTL_BLKSZ(6) /*!< block size = 64 bytes */ +#define SDIO_DATABLOCKSIZE_128BYTES DATACTL_BLKSZ(7) /*!< block size = 128 bytes */ +#define SDIO_DATABLOCKSIZE_256BYTES DATACTL_BLKSZ(8) /*!< block size = 256 bytes */ +#define SDIO_DATABLOCKSIZE_512BYTES DATACTL_BLKSZ(9) /*!< block size = 512 bytes */ +#define SDIO_DATABLOCKSIZE_1024BYTES DATACTL_BLKSZ(10) /*!< block size = 1024 bytes */ +#define SDIO_DATABLOCKSIZE_2048BYTES DATACTL_BLKSZ(11) /*!< block size = 2048 bytes */ +#define SDIO_DATABLOCKSIZE_4096BYTES DATACTL_BLKSZ(12) /*!< block size = 4096 bytes */ +#define SDIO_DATABLOCKSIZE_8192BYTES DATACTL_BLKSZ(13) /*!< block size = 8192 bytes */ +#define SDIO_DATABLOCKSIZE_16384BYTES DATACTL_BLKSZ(14) /*!< block size = 16384 bytes */ + +/* SDIO data transfer mode */ +#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000U)/*!< block transfer */ +#define SDIO_TRANSMODE_STREAM SDIO_DATACTL_TRANSMOD /*!< stream transfer or SDIO multibyte transfer */ + +/* SDIO data transfer direction */ +#define SDIO_TRANSDIRECTION_TOCARD ((uint32_t)0x00000000U)/*!< write data to card */ +#define SDIO_TRANSDIRECTION_TOSDIO SDIO_DATACTL_DATADIR /*!< read data from card */ + +/* SDIO read wait type */ +#define SDIO_READWAITTYPE_DAT2 ((uint32_t)0x00000000U)/*!< read wait control using SDIO_DAT[2] */ +#define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize the SDIO */ +void sdio_deinit(void); +/* configure the SDIO clock */ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division); +/* enable hardware clock control */ +void sdio_hardware_clock_enable(void); +/* disable hardware clock control */ +void sdio_hardware_clock_disable(void); +/* set different SDIO card bus mode */ +void sdio_bus_mode_set(uint32_t bus_mode); +/* set the SDIO power state */ +void sdio_power_state_set(uint32_t power_state); +/* get the SDIO power state */ +uint32_t sdio_power_state_get(void); +/* enable SDIO_CLK clock output */ +void sdio_clock_enable(void); +/* disable SDIO_CLK clock output */ +void sdio_clock_disable(void); + +/* function configuration */ +/* configure the command index, argument, response type, wait type and CSM to send command */ +/* configure the command and response */ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); +/* set the command state machine wait type */ +void sdio_wait_type_set(uint32_t wait_type); +/* enable the CSM(command state machine) */ +void sdio_csm_enable(void); +/* disable the CSM(command state machine) */ +void sdio_csm_disable(void); +/* get the last response command index */ +uint8_t sdio_command_index_get(void); +/* get the response for the last received command */ +uint32_t sdio_response_get(uint32_t responsex); + +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer */ +/* configure the data timeout, data length and data block size */ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); +/* configure the data transfer mode and direction */ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction); +/* enable the DSM(data state machine) for data transfer */ +void sdio_dsm_enable(void); +/* disable the DSM(data state machine) */ +void sdio_dsm_disable(void); +/* write data(one word) to the transmit FIFO */ +void sdio_data_write(uint32_t data); +/* read data(one word) from the receive FIFO */ +uint32_t sdio_data_read(void); +/* get the number of remaining data bytes to be transferred to card */ +uint32_t sdio_data_counter_get(void); +/* get the number of words remaining to be written or read from FIFO */ +uint32_t sdio_fifo_counter_get(void); +/* enable the DMA request for SDIO */ +void sdio_dma_enable(void); +/* disable the DMA request for SDIO */ +void sdio_dma_disable(void); + +/* enable the read wait mode(SD I/O only) */ +void sdio_readwait_enable(void); +/* disable the read wait mode(SD I/O only) */ +void sdio_readwait_disable(void); +/* enable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_enable(void); +/* disable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_disable(void); +/* set the read wait type(SD I/O only) */ +void sdio_readwait_type_set(uint32_t readwait_type); +/* enable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_enable(void); +/* disable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_disable(void); +/* enable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_enable(void); +/* disable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_disable(void); + +/* enable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_enable(void); +/* disable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_disable(void); +/* enable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_enable(void); +/* disable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_disable(void); +/* enable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_enable(void); +/* disable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_disable(void); + +/* interrupt & flag functions */ +/* get the flags state of SDIO */ +FlagStatus sdio_flag_get(uint32_t flag); +/* clear the pending flags of SDIO */ +void sdio_flag_clear(uint32_t flag); +/* enable the SDIO interrupt */ +void sdio_interrupt_enable(uint32_t int_flag); +/* disable the SDIO interrupt */ +void sdio_interrupt_disable(uint32_t int_flag); +/* get the interrupt flags state of SDIO */ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); +/* clear the interrupt pending flags of SDIO */ +void sdio_interrupt_flag_clear(uint32_t int_flag); + +#endif /* GD32F20X_SDIO_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h new file mode 100644 index 0000000000..f5e2d49280 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h @@ -0,0 +1,346 @@ +/*! + \file gd32f20x_spi.h + \brief definitions for the SPI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_SPI_H +#define GD32F20X_SPI_H + +#include "gd32f20x.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ +#define SPI_QCTL(spix) REG32((spix) + 0x80U) /*!< SPI quad mode control register(only SPI0) */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3,5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR BITS(0,15) /*!< CRC polynomial register */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC register */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCR BITS(0,15) /*!< RX CRC register */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4,5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8,9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* SPI_QCTL(only for SPI0) */ +#define SPI_QCTL_QMOD BIT(0) /*!< quad-SPI mode enable */ +#define SPI_QCTL_QRD BIT(1) /*!< quad-SPI mode read select */ +#define SPI_QCTL_IO23_DRV BIT(2) /*!< drive SPI_IO2 and SPI_IO3 enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transfer type */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by hardware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescaler factor */ +}spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE ~SPI_CTL0_BDOEN /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by sofrware */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1,2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI structure with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* DMA communication */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* normal mode communication */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +/* enable quad wire SPI */ +void qspi_enable(uint32_t spi_periph); +/* disable quad wire SPI */ +void qspi_disable(uint32_t spi_periph); +/* enable quad wire SPI write */ +void qspi_write_enable(uint32_t spi_periph); +/* enable quad wire SPI read */ +void qspi_read_enable(uint32_t spi_periph); +/* enable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_enable(uint32_t spi_periph); +/* disable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_disable(uint32_t spi_periph); + +#endif /* GD32F20X_SPI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h new file mode 100644 index 0000000000..d0e0221a54 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h @@ -0,0 +1,731 @@ +/*! + \file gd32f20x_timer.h + \brief definitions for the TIMER + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_TIMER_H +#define GD32F20X_TIMER_H + +#include "gd32f20x.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) +#define TIMER7 (TIMER_BASE + 0x00013400U) +#define TIMER8 (TIMER_BASE + 0x00014C00U) +#define TIMER9 (TIMER_BASE + 0x00015000U) +#define TIMER10 (TIMER_BASE + 0x00015400U) +#define TIMER11 (TIMER_BASE + 0x00001800U) +#define TIMER12 (TIMER_BASE + 0x00001C00U) +#define TIMER13 (TIMER_BASE + 0x00002000U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER channel complementary protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5,6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0,2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4,6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8,11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 over capture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 over capture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 over capture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 over capture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0,1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4,6) /*!< channel 0 output compare control */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8,9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12,14) /*!< channel 1 output compare control */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2,3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4,7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10,11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12,15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0,1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4,6) /*!< channel 2 output compare control */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8,9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12,14) /*!< channel 3 output compare control */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2,3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4,7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10,11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0,15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0,15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0,15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0,7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8,9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0,4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8,12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0,15) /*!< DMA transfer buffer address */ + +/* constants definitions */ +/* TIMER init parameter structure definitions */ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint32_t period; /*!< period value */ + uint16_t clockdivision; /*!< clock division value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +}timer_parameter_struct; + +/* break parameter structure definitions*/ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +}timer_break_parameter_struct; + +/* channel output parameter structure definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +}timer_oc_parameter_struct; + +/* channel input parameter structure definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +}timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INT_UP /*!< update interrupt */ +#define TIMER_INT_FLAG_CH0 TIMER_INT_CH0 /*!< channel 0 interrupt */ +#define TIMER_INT_FLAG_CH1 TIMER_INT_CH1 /*!< channel 1 interrupt */ +#define TIMER_INT_FLAG_CH2 TIMER_INT_CH2 /*!< channel 2 interrupt */ +#define TIMER_INT_FLAG_CH3 TIMER_INT_CH3 /*!< channel 3 interrupt */ +#define TIMER_INT_FLAG_CMT TIMER_INT_CMT /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INT_TRG /*!< trigger interrupt */ +#define TIMER_INT_FLAG_BRK TIMER_INT_BRK + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ + +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT TIMER_CTL1_DMAS /*!< DMA request of channel n is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel n is sent when channel n event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA_DMATB DMACFG_DMATA(19) /*!< DMA transfer address is TIMER_DMATB */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW TIMER_SWEVG_UPG /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000000U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE TIMER_CTL0_SPM /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000000U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR TIMER_CTL0_UPS /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000000U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4,7)) */ + +/* channel enable state */ +#define TIMER_CCX_ENABLE ((uint16_t)0x0001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint16_t)0x0000U) /*!< channel disable */ + +/* channel complementary output enable state */ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< frozen mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< set the channel output */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< clear the channel output */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle on match */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode*/ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers update by when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI TIMER_CTL1_CCUC /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ +#define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ + +/* timer input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4 */ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channel 0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE TIMER_SMCFG_MSM /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000000U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE TIMER_CTL1_TI0S /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0..4,7..13) write CHxVAL register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)TIMER_CFG_OUTSEL) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* function declarations */ +/* TIMER timebase */ +/* deinit a TIMER */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter structure */ +void timer_struct_para_init(timer_parameter_struct* initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +/* enable a TIMER */ +void timer_enable(uint32_t timer_periph); +/* disable a TIMER */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* timer DMA and event */ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter structure */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER interrupt and flag */ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flag */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flag */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +#endif /* GD32F20X_TIMER_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h new file mode 100644 index 0000000000..b6b9818a98 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h @@ -0,0 +1,368 @@ +/*! + \file gd32f20x_tli.h + \brief definitions for the TLI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_TLI_H +#define GD32F20X_TLI_H + +#include "gd32f20x.h" + +/* TLI definitions */ +#define TLI TLI_BASE /*!< TLI base address */ +/* TLI layer definitions */ +#define LAYER0 TLI_BASE /*!< Layer0 base address */ +#define LAYER1 (TLI_BASE + 0x80) /*!< Layer1 base address */ + +/* registers definitions */ +#define TLI_SPSZ REG32(TLI + 0x08U) /*!< TLI synchronous pulse size register */ +#define TLI_BPSZ REG32(TLI + 0x0CU) /*!< TLI back-porch size register */ +#define TLI_ASZ REG32(TLI + 0x10U) /*!< TLI active size register */ +#define TLI_TSZ REG32(TLI + 0x14U) /*!< TLI total size register */ +#define TLI_CTL REG32(TLI + 0x18U) /*!< TLI control register */ +#define TLI_RL REG32(TLI + 0x24U) /*!< TLI reload layer register */ +#define TLI_BGC REG32(TLI + 0x2CU) /*!< TLI background color register */ +#define TLI_INTEN REG32(TLI + 0x34U) /*!< TLI interrupt enable register */ +#define TLI_INTF REG32(TLI + 0x38U) /*!< TLI interrupt flag register */ +#define TLI_INTC REG32(TLI + 0x3CU) /*!< TLI interrupt flag clear register */ +#define TLI_LM REG32(TLI + 0x40U) /*!< TLI line mark register */ +#define TLI_CPPOS REG32(TLI + 0x44U) /*!< TLI current pixel position register */ +#define TLI_STAT REG32(TLI + 0x48U) /*!< TLI status register */ +#define TLI_LxCTL(layerx) REG32((layerx) + 0x84U) /*!< TLI layer x control register */ +#define TLI_LxHPOS(layerx) REG32((layerx) + 0x88U) /*!< TLI layer x horizontal position parameters register */ +#define TLI_LxVPOS(layerx) REG32((layerx) + 0x8CU) /*!< TLI layer x vertical position parameters register */ +#define TLI_LxCKEY(layerx) REG32((layerx) + 0x90U) /*!< TLI layer x color key register */ +#define TLI_LxPPF(layerx) REG32((layerx) + 0x94U) /*!< TLI layer x packeted pixel format register */ +#define TLI_LxSA(layerx) REG32((layerx) + 0x98U) /*!< TLI layer x specified alpha register */ +#define TLI_LxDC(layerx) REG32((layerx) + 0x9CU) /*!< TLI layer x default color register */ +#define TLI_LxBLEND(layerx) REG32((layerx) + 0xA0U) /*!< TLI layer x blending register */ +#define TLI_LxFBADDR(layerx) REG32((layerx) + 0xACU) /*!< TLI layer x frame base address register */ +#define TLI_LxFLLEN(layerx) REG32((layerx) + 0xB0U) /*!< TLI layer x frame line length register */ +#define TLI_LxFTLN(layerx) REG32((layerx) + 0xB4U) /*!< TLI layer x frame total line number register */ +#define TLI_LxLUT(layerx) REG32((layerx) + 0xC4U) /*!< TLI layer x look up table register */ + +/* bits definitions */ +/* TLI_SPSZ */ +#define TLI_SPSZ_VPSZ BITS(0,11) /*!< size of the vertical synchronous pulse */ +#define TLI_SPSZ_HPSZ BITS(16,27) /*!< size of the horizontal synchronous pulse */ + +/* TLI_BPSZ */ +#define TLI_BPSZ_VBPSZ BITS(0,11) /*!< size of the vertical back porch plus synchronous pulse */ +#define TLI_BPSZ_HBPSZ BITS(16,27) /*!< size of the horizontal back porch plus synchronous pulse */ + +/* TLI_ASZ */ +#define TLI_ASZ_VASZ BITS(0,11) /*!< size of the vertical active area width plus back porch and synchronous pulse */ +#define TLI_ASZ_HASZ BITS(16,27) /*!< size of the horizontal active area width plus back porch and synchronous pulse */ + +/* TLI_TSZ */ +#define TLI_TSZ_VTSZ BITS(0,11) /*!< vertical total size of the display, including active area, back porch, synchronous pulse and front porch */ +#define TLI_TSZ_HTSZ BITS(16,27) /*!< horizontal total size of the display, including active area, back porch, synchronous pulse and front porch */ + +/* TLI_CTL */ +#define TLI_CTL_TLIEN BIT(0) /*!< TLI enable bit */ +#define TLI_CTL_BDB BITS(4,6) /*!< blue channel dither bits number */ +#define TLI_CTL_GDB BITS(8,10) /*!< green channel dither bits number */ +#define TLI_CTL_RDB BITS(12,14) /*!< red channel dither bits number */ +#define TLI_CTL_DFEN BIT(16) /*!< dither function enable */ +#define TLI_CTL_CLKPS BIT(28) /*!< pixel clock polarity selection */ +#define TLI_CTL_DEPS BIT(29) /*!< data enable polarity selection */ +#define TLI_CTL_VPPS BIT(30) /*!< vertical pulse polarity selection */ +#define TLI_CTL_HPPS BIT(31) /*!< horizontal pulse polarity selection */ + +/* TLI_RL */ +#define TLI_RL_RQR BIT(0) /*!< request reload */ +#define TLI_RL_FBR BIT(1) /*!< frame blank reload */ + +/* TLI_BGC */ +#define TLI_BGC_BVB BITS(0,7) /*!< background value blue */ +#define TLI_BGC_BVG BITS(8,15) /*!< background value green */ +#define TLI_BGC_BVR BITS(16,23) /*!< background value red */ + +/* TLI_INTEN */ +#define TLI_INTEN_LMIE BIT(0) /*!< line mark interrupt enable */ +#define TLI_INTEN_FEIE BIT(1) /*!< FIFO error interrupt enable */ +#define TLI_INTEN_TEIE BIT(2) /*!< transaction error interrupt enable */ +#define TLI_INTEN_LCRIE BIT(3) /*!< layer configuration reloaded interrupt enable */ + +/* TLI_INTF */ +#define TLI_INTF_LMF BIT(0) /*!< line mark flag */ +#define TLI_INTF_FEF BIT(1) /*!< FIFO error flag */ +#define TLI_INTF_TEF BIT(2) /*!< transaction error flag */ +#define TLI_INTF_LCRF BIT(3) /*!< layer configuration reloaded flag */ + +/* TLI_INTC */ +#define TLI_INTC_LMC BIT(0) /*!< line mark flag clear */ +#define TLI_INTC_FEC BIT(1) /*!< FIFO error flag clear */ +#define TLI_INTC_TEC BIT(2) /*!< transaction error flag clear */ +#define TLI_INTC_LCRC BIT(3) /*!< layer configuration reloaded flag clear */ + +/* TLI_LM */ +#define TLI_LM_LM BITS(0,10) /*!< line mark value */ + +/* TLI_CPPOS */ +#define TLI_CPPOS_VPOS BITS(0,15) /*!< vertical position */ +#define TLI_CPPOS_HPOS BITS(16,31) /*!< horizontal position */ + +/* TLI_STAT */ +#define TLI_STAT_VDE BIT(0) /*!< current VDE status */ +#define TLI_STAT_HDE BIT(1) /*!< current HDE status */ +#define TLI_STAT_VS BIT(2) /*!< current VS status of the TLI */ +#define TLI_STAT_HS BIT(3) /*!< current HS status of the TLI */ + +/* TLI_LxCTL */ +#define TLI_LxCTL_LEN BIT(0) /*!< layer enable */ +#define TLI_LxCTL_CKEYEN BIT(1) /*!< color keying enable */ +#define TLI_LxCTL_LUTEN BIT(4) /*!< LUT enable */ + +/* TLI_LxHPOS */ +#define TLI_LxHPOS_WLP BITS(0,11) /*!< window left position */ +#define TLI_LxHPOS_WRP BITS(16,27) /*!< window right position */ + +/* TLI_LxVPOS */ +#define TLI_LxVPOS_WTP BITS(0,11) /*!< window top position */ +#define TLI_LxVPOS_WBP BITS(16,27) /*!< window bottom position */ + +/* TLI_LxCKEY */ +#define TLI_LxCKEY_CKEYB BITS(0,7) /*!< color key blue */ +#define TLI_LxCKEY_CKEYG BITS(8,15) /*!< color key green */ +#define TLI_LxCKEY_CKEYR BITS(16,23) /*!< color key red */ + +/* TLI_LxPPF */ +#define TLI_LxPPF_PPF BITS(0,2) /*!< packeted pixel format */ + +/* TLI_LxSA */ +#define TLI_LxSA_SA BITS(0,7) /*!< specified alpha */ + +/* TLI_LxDC */ +#define TLI_LxDC_DCB BITS(0,7) /*!< the default color blue */ +#define TLI_LxDC_DCG BITS(8,15) /*!< the default color green */ +#define TLI_LxDC_DCR BITS(16,23) /*!< the default color red */ +#define TLI_LxDC_DCA BITS(24,31) /*!< the default color alpha */ + +/* TLI_LxBLEND */ +#define TLI_LxBLEND_ACF2 BITS(0,2) /*!< alpha calculation factor 2 of blending method */ +#define TLI_LxBLEND_ACF1 BITS(8,10) /*!< alpha calculation factor 1 of blending method */ + +/* TLI_LxFBADDR */ +#define TLI_LxFBADDR_FBADD BITS(0,31) /*!< frame buffer base address */ + +/* TLI_LxFLLEN */ +#define TLI_LxFLLEN_FLL BITS(0,13) /*!< frame line length */ +#define TLI_LxFLLEN_STDOFF BITS(16,29) /*!< frame buffer stride offset */ + +/* TLI_LxFTLN */ +#define TLI_LxFTLN_FTLN BITS(0,10) /*!< frame total line number */ + +/* TLI_LxLUT */ +#define TLI_LxLUT_TB BITS(0,7) /*!< blue channel of a LUT entry */ +#define TLI_LxLUT_TG BITS(8,15) /*!< green channel of a LUT entry */ +#define TLI_LxLUT_TR BITS(16,23) /*!< red channel of a LUT entry */ +#define TLI_LxLUT_TADD BITS(24,31) /*!< look up table write address */ + +/* constants definitions */ +/* TLI parameter structure definitions */ +typedef struct +{ + uint32_t synpsz_vpsz; /*!< size of the vertical synchronous pulse */ + uint32_t synpsz_hpsz; /*!< size of the horizontal synchronous pulse */ + uint32_t backpsz_vbpsz; /*!< size of the vertical back porch plus synchronous pulse */ + uint32_t backpsz_hbpsz; /*!< size of the horizontal back porch plus synchronous pulse */ + uint32_t activesz_vasz; /*!< size of the vertical active area width plus back porch and synchronous pulse */ + uint32_t activesz_hasz; /*!< size of the horizontal active area width plus back porch and synchronous pulse */ + uint32_t totalsz_vtsz; /*!< vertical total size of the display */ + uint32_t totalsz_htsz; /*!< horizontal total size of the display */ + uint32_t backcolor_red; /*!< background value red */ + uint32_t backcolor_green; /*!< background value green */ + uint32_t backcolor_blue; /*!< background value blue */ + uint32_t signalpolarity_hs; /*!< horizontal pulse polarity selection */ + uint32_t signalpolarity_vs; /*!< vertical pulse polarity selection */ + uint32_t signalpolarity_de; /*!< data enable polarity selection */ + uint32_t signalpolarity_pixelck; /*!< pixel clock polarity selection */ +}tli_parameter_struct; + +/* TLI layer parameter structure definitions */ +typedef struct +{ + uint32_t layer_window_rightpos; /*!< window right position */ + uint32_t layer_window_leftpos; /*!< window left position */ + uint32_t layer_window_bottompos; /*!< window bottom position */ + uint32_t layer_window_toppos; /*!< window top position */ + uint32_t layer_ppf; /*!< packeted pixel format */ + uint32_t layer_sa; /*!< specified alpha */ + uint32_t layer_default_alpha; /*!< the default color alpha */ + uint32_t layer_default_red; /*!< the default color red */ + uint32_t layer_default_green; /*!< the default color green */ + uint32_t layer_default_blue; /*!< the default color blue */ + uint32_t layer_acf1; /*!< alpha calculation factor 1 of blending method */ + uint32_t layer_acf2; /*!< alpha calculation factor 2 of blending method */ + uint32_t layer_frame_bufaddr; /*!< frame buffer base address */ + uint32_t layer_frame_buf_stride_offset; /*!< frame buffer stride offset */ + uint32_t layer_frame_line_length; /*!< frame line length */ + uint32_t layer_frame_total_line_number; /*!< frame total line number */ +}tli_layer_parameter_struct; + +/* TLI layer LUT parameter structure definitions */ +typedef struct +{ + uint32_t layer_table_addr; /*!< look up table write address */ + uint32_t layer_lut_channel_red; /*!< red channel of a LUT entry */ + uint32_t layer_lut_channel_green; /*!< green channel of a LUT entry */ + uint32_t layer_lut_channel_blue; /*!< blue channel of a LUT entry */ +}tli_layer_lut_parameter_struct; + +/* packeted pixel format */ +typedef enum +{ + LAYER_PPF_ARGB8888, /*!< layerx packeted pixel format ARGB8888 */ + LAYER_PPF_RGB888, /*!< layerx packeted pixel format RGB888 */ + LAYER_PPF_RGB565, /*!< layerx packeted pixel format RGB565 */ + LAYER_PPF_ARGB1555, /*!< layerx packeted pixel format ARGB1555 */ + LAYER_PPF_ARGB4444, /*!< layerx packeted pixel format ARGB4444 */ + LAYER_PPF_L8, /*!< layerx packeted pixel format L8 */ + LAYER_PPF_AL44, /*!< layerx packeted pixel format AL44 */ + LAYER_PPF_AL88 /*!< layerx packeted pixel format AL88 */ +} tli_layer_ppf_enum; + +/* TLI flags and states */ +#define TLI_FLAG_VDE TLI_STAT_VDE /*!< current VDE status */ +#define TLI_FLAG_HDE TLI_STAT_HDE /*!< current HDE status */ +#define TLI_FLAG_VS TLI_STAT_VS /*!< current VS status of the TLI */ +#define TLI_FLAG_HS TLI_STAT_HS /*!< current HS status of the TLI */ +#define TLI_FLAG_LM (BIT(0) | BIT(31)) /*!< line mark interrupt flag */ +#define TLI_FLAG_FE (BIT(1) | BIT(31)) /*!< FIFO error interrupt flag */ +#define TLI_FLAG_TE (BIT(2) | BIT(31)) /*!< transaction error interrupt flag */ +#define TLI_FLAG_LCR (BIT(3) | BIT(31)) /*!< layer configuration reloaded interrupt flag */ + +/* TLI interrupt enable or disable */ +#define TLI_INT_LM BIT(0) /*!< line mark interrupt */ +#define TLI_INT_FE BIT(1) /*!< FIFO error interrupt */ +#define TLI_INT_TE BIT(2) /*!< transaction error interrupt */ +#define TLI_INT_LCR BIT(3) /*!< layer configuration reloaded interrupt */ + +/* TLI interrupt flag */ +#define TLI_INT_FLAG_LM BIT(0) /*!< line mark interrupt flag */ +#define TLI_INT_FLAG_FE BIT(1) /*!< FIFO error interrupt flag */ +#define TLI_INT_FLAG_TE BIT(2) /*!< transaction error interrupt flag */ +#define TLI_INT_FLAG_LCR BIT(3) /*!< layer configuration reloaded interrupt flag */ + +/* layer reload configure */ +#define TLI_FRAME_BLANK_RELOAD_EN ((uint8_t)0x00U) /*!< the layer configuration will be reloaded at frame blank */ +#define TLI_REQUEST_RELOAD_EN ((uint8_t)0x01U) /*!< the layer configuration will be reloaded after this bit sets */ + +/* dither function */ +#define TLI_DITHER_DISABLE ((uint8_t)0x00U) /*!< dither function disable */ +#define TLI_DITHER_ENABLE ((uint8_t)0x01U) /*!< dither function enable */ + +/* horizontal pulse polarity selection */ +#define TLI_HSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< horizontal synchronous pulse active low */ +#define TLI_HSYN_ACTLIVE_HIGHT TLI_CTL_HPPS /*!< horizontal synchronous pulse active high */ + +/* vertical pulse polarity selection */ +#define TLI_VSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< vertical synchronous pulse active low */ +#define TLI_VSYN_ACTLIVE_HIGHT TLI_CTL_VPPS /*!< vertical synchronous pulse active high */ + +/* pixel clock polarity selection */ +#define TLI_PIXEL_CLOCK_TLI ((uint32_t)0x00000000U) /*!< pixel clock is TLI clock */ +#define TLI_PIXEL_CLOCK_INVERTEDTLI TLI_CTL_CLKPS /*!< pixel clock is inverted TLI clock */ + +/* data enable polarity selection */ +#define TLI_DE_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< data enable active low */ +#define TLI_DE_ACTLIVE_HIGHT TLI_CTL_DEPS /*!< data enable active high */ + +/* alpha calculation factor 1 of blending method */ +#define LxBLEND_ACF1(regval) (BITS(8,10) & ((regval)<<8)) +#define LAYER_ACF1_SA LxBLEND_ACF1(4) /*!< normalization specified alpha */ +#define LAYER_ACF1_PASA LxBLEND_ACF1(6) /*!< normalization pixel alpha * normalization specified alpha */ + +/* alpha calculation factor 2 of blending method */ +#define LxBLEND_ACF2(regval) (BITS(0,2) & ((regval))) +#define LAYER_ACF2_SA LxBLEND_ACF2(5) /*!< normalization specified alpha */ +#define LAYER_ACF2_PASA LxBLEND_ACF2(7) /*!< normalization pixel alpha * normalization specified alpha */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize TLI */ +void tli_deinit(void); +/* initialize TLI */ +void tli_init(tli_parameter_struct *tli_struct); +/* configure TLI dither function */ +void tli_dither_config(uint8_t ditherstat); +/* enable TLI */ +void tli_enable(void); +/* disable TLI */ +void tli_disable(void); +/* configure TLI reload mode */ +void tli_reload_config(uint8_t reloadmode); + +/* set line mark value */ +void tli_line_mark_set(uint32_t linenum); +/* get current displayed position */ +uint32_t tli_current_pos_get(void); + +/* function configuration */ +/* TLI layer enable */ +void tli_layer_enable(uint32_t layerx); +/* TLI layer disable */ +void tli_layer_disable(uint32_t layerx); +/* TLI layer color keying enable */ +void tli_color_key_enable(uint32_t layerx); +/* TLI layer color keying disable */ +void tli_color_key_disable(uint32_t layerx); +/* TLI layer LUT enable */ +void tli_lut_enable(uint32_t layerx); +/* TLI layer LUT disable */ +void tli_lut_disable(uint32_t layerx); +/* TLI layer initialize */ +void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct); +/* TLI layer initialize */ +void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y); +/* TLI layer LUT initialize */ +void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct); +/* TLI layer key initialize */ +void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey); + +/* interrupt & flag functions */ +/* get TLI flag or state */ +FlagStatus tli_flag_get(uint32_t flag); +/* enable TLI interrupt */ +void tli_interrupt_enable(uint32_t interrupt); +/* disable TLI interrupt */ +void tli_interrupt_disable(uint32_t interrupt); +/* get TLI interrupt flag */ +FlagStatus tli_interrupt_flag_get(uint32_t int_flag); +/* clear TLI interrupt flag */ +void tli_interrupt_flag_clear(uint32_t int_flag); + +#endif /* GD32F20X_TLI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h new file mode 100644 index 0000000000..164b372869 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h @@ -0,0 +1,105 @@ +/*! + \file gd32f20x_trng.h + \brief definitions for the TRNG + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_TRNG_H +#define GD32F20X_TRNG_H + +#include "gd32f20x.h" + +/* TRNG definitions */ +#define TRNG TRNG_BASE + +/* registers definitions */ +#define TRNG_CTL REG32(TRNG + 0x00U) /*!< control register */ +#define TRNG_STAT REG32(TRNG + 0x04U) /*!< status register */ +#define TRNG_DATA REG32(TRNG + 0x08U) /*!< data register */ + +/* bits definitions */ +/* TRNG_CTL */ +#define TRNG_CTL_TRNGEN BIT(2) /*!< TRNG enable bit */ +#define TRNG_CTL_IE BIT(3) /*!< interrupt enable bit */ + +/* TRNG_STAT */ +#define TRNG_STAT_DRDY BIT(0) /*!< random data ready status bit */ +#define TRNG_STAT_CECS BIT(1) /*!< clock error current status */ +#define TRNG_STAT_SECS BIT(2) /*!< seed error current status */ +#define TRNG_STAT_CEIF BIT(5) /*!< clock error interrupt flag */ +#define TRNG_STAT_SEIF BIT(6) /*!< seed error interrupt flag */ + +/* TRNG_DATA */ +#define TRNG_DATA_TRNDATA BITS(0,31) /*!< 32-Bit Random data */ + +/* constants definitions */ +/* trng status flag */ +typedef enum +{ + TRNG_FLAG_DRDY = TRNG_STAT_DRDY, /*!< random Data ready status */ + TRNG_FLAG_CECS = TRNG_STAT_CECS, /*!< clock error current status */ + TRNG_FLAG_SECS = TRNG_STAT_SECS /*!< seed error current status */ +}trng_flag_enum; + +/* trng inerrupt flag */ +typedef enum +{ + TRNG_INT_FLAG_CE = TRNG_STAT_CEIF, /*!< clock error interrupt flag */ + TRNG_INT_FLAG_SE = TRNG_STAT_SEIF /*!< seed error interrupt flag */ +}trng_int_flag_enum; + +/* function declarations */ +/* initialization functions */ +/* deinitialize the TRNG */ +void trng_deinit(void); +/* enable the TRNG interface */ +void trng_enable(void); +/* disable the TRNG interface */ +void trng_disable(void); +/* get the true random data */ +uint32_t trng_get_true_random_data(void); + +/* interrupt & flag functions */ +/* get the trng status flags */ +FlagStatus trng_flag_get(trng_flag_enum flag); +/* the trng interrupt enable */ +void trng_interrupt_enable(void); +/* the trng interrupt disable */ +void trng_interrupt_disable(void); +/* get the trng interrupt flags */ +FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag); +/* clear the trng interrupt flags */ +void trng_interrupt_flag_clear(trng_int_flag_enum int_flag); + +#endif /* GD32F20X_TRNG_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h new file mode 100644 index 0000000000..a4c9b78846 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h @@ -0,0 +1,449 @@ +/*! + \file gd32f20x_usart.h + \brief definitions for the USART + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_USART_H +#define GD32F20X_USART_H + +#include "gd32f20x.h" + +/* USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE+0x00000400U) /*!< USART2 base address */ +#define UART3 (USART_BASE+0x00000800U) /*!< UART3 base address */ +#define UART4 (USART_BASE+0x00000C00U) /*!< UART4 base address */ +#define UART6 (USART_BASE+0x00003400U) /*!< UART6 base address */ +#define UART7 (USART_BASE+0x00003800U) /*!< UART7 base address */ +#define USART0 (USART_BASE+0x0000F400U) /*!< USART0 base address */ +#define USART5 (USART_BASE+0x00012C00U) /*!< USART5 base address */ + +/* registers definitions */ +#define USART_STAT0(usartx) REG32((usartx) + 0x00U) /*!< USART status register 0 */ +#define USART_DATA(usartx) REG32((usartx) + 0x04U) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + 0x08U) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + 0x0CU) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + 0x10U) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + 0x14U) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + 0x18U) /*!< USART guard time and prescaler register */ +#define USART_CTL3(usartx) REG32((usartx) + 0x80U) /*!< USART control register 3 */ +#define USART_RT(usartx) REG32((usartx) + 0x84U) /*!< USART receiver timeout register */ +#define USART_STAT1(usartx) REG32((usartx) + 0x88U) /*!< USART status register 1 */ + +/* bits definitions */ +/* USARTx_STAT0 */ +#define USART_STAT0_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT0_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT0_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT0_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT0_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT0_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT0_TC BIT(6) /*!< transmission complete */ +#define USART_STAT0_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT0_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT0_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + +/* USARTx_CTL3 */ +#define USART_CTL3_RTEN BIT(0) /*!< receiver timeout enable */ +#define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ +#define USART_CTL3_RTIE BIT(4) /*!< interrupt enable bit of receive timeout event */ +#define USART_CTL3_EBIE BIT(5) /*!< interrupt enable bit of end of block event */ +#define USART_CTL3_RINV BIT(8) /*!< RX pin level inversion */ +#define USART_CTL3_TINV BIT(9) /*!< TX pin level inversion */ +#define USART_CTL3_DINV BIT(10) /*!< data bit level inversion */ +#define USART_CTL3_MSBF BIT(11) /*!< most significant bit first */ + +/* USARTx_RT */ +#define USART_RT_RT BITS(0,23) /*!< receiver timeout threshold */ +#define USART_RT_BL BITS(24,31) /*!< block length */ + +/* USARTx_STAT1 */ +#define USART_STAT1_RTF BIT(11) /*!< receiver timeout flag */ +#define USART_STAT1_EBF BIT(12) /*!< end of block flag */ +#define USART_STAT1_BSY BIT(16) /*!< busy flag */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define USART_STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ +#define USART_STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ +#define USART_CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ +#define USART_CTL3_REG_OFFSET 0x80U /*!< CTL3 register offset */ + +/* USART flags */ +typedef enum +{ + /* flags in STAT0 register */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ + /* flags in STAT1 register */ + USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ + USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ + USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ +}usart_flag_enum; + +/* USART interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT0_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT0_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ + /* interrupt flags in CTL3 register */ + USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U), /*!< interrupt enable bit of end of block event and flag */ + USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U), /*!< interrupt enable bit of receive timeout event and flag */ +}usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ + /* interrupt in CTL3 register */ + USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U), /*!< end of block interrupt */ + USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U), /*!< receive timeout interrupt */ +}usart_interrupt_enum; + +/* USART invert configure */ +typedef enum +{ + /* data bit level inversion */ + USART_DINV_ENABLE, /*!< data bit level inversion */ + USART_DINV_DISABLE, /*!< data bit level not inversion */ + /* TX pin level inversion */ + USART_TXPIN_ENABLE, /*!< TX pin level inversion */ + USART_TXPIN_DISABLE, /*!< TX pin level not inversion */ + /* RX pin level inversion */ + USART_RXPIN_ENABLE, /*!< RX pin level inversion */ + USART_RXPIN_DISABLE, /*!< RX pin level not inversion */ +}usart_invert_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* USART data is transmitted/received with the LSB/MSB first */ +#define CTL3_MSBF(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_MSBF_LSB CTL3_MSBF(0) /*!< LSB first */ +#define USART_MSBF_MSB CTL3_MSBF(1) /*!< MSB first */ + + + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); + +/* function configuration */ +/* USART normal mode communication */ +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); +/* data is transmitted/received with the LSB/MSB first */ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf); +/* configure USART inverted */ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara); +/* enable receiver timeout */ +void usart_receiver_timeout_enable(uint32_t usart_periph); +/* disable receiver timeout */ +void usart_receiver_timeout_disable(uint32_t usart_periph); +/* configure receiver timeout threshold */ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint16_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* LIN mode enable */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* LIN mode disable */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* half-duplex enable */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* half-duplex disable */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* clock enable */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* clock disable */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* guard time value configure in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat); +/* smartcard mode enable */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* smartcard mode disable */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* NACK enable in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* NACK disable in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); +/* smartcard auto-retry number configure */ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum); +/* block length configure */ +void usart_block_length_config(uint32_t usart_periph, uint32_t bl); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* interrupt & flag functions */ +/* get flag in STAT0/STAT1 register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT0/STAT1 register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); +/* clear interrupt flag in STAT0/STAT1 register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag); + +#endif /* GD32F20X_USART_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h new file mode 100644 index 0000000000..1b11009455 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h @@ -0,0 +1,91 @@ +/*! + \file gd32f20x_wwdgt.h + \brief definitions for the WWDGT + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_WWDGT_H +#define GD32F20X_WWDGT_H + +#include "gd32f20x.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE /*!< WWDGT base address */ + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x04U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x08U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0,6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0,6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7,8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* initialization functions */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* interrupt & flag functions */ +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32F20X_WWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c new file mode 100644 index 0000000000..567165855e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c @@ -0,0 +1,1019 @@ +/*! + \file gd32f20x_adc.c + \brief ADC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_adc.h" + +/* discontinuous mode macro*/ +#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U) + +/* ADC regular channel macro */ +#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U) +#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U) +#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U) +#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U) + +/* ADC sampling time macro */ +#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U) +#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U) +#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U) + +/* ADC inserted channel macro */ +#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U) +#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U) + +/* ADC inserted channel offset macro */ +#define ADC_OFFSET_LENGTH ((uint8_t)3U) +#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + /* reset ADC0 */ + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + /* reset ADC1 */ + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; + case ADC2: + /* reset ADC2 */ + rcu_periph_reset_enable(RCU_ADC2RST); + rcu_periph_reset_disable(RCU_ADC2RST); + break; + default: + break; + } +} + +/*! + \brief configure the ADC sync mode(only for ADC0) + \param[in] mode: ADC mode + only one parameter can be selected which is shown as below: + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] function: the function to configure + one or more parameters can be selected below + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] new_value: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus new_value) +{ + if(new_value){ + if(0U != (function & ADC_SCAN_MODE)){ + /* enable ADC scan mode */ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* enable ADC inserted channel group convert automatically */ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* enable ADC continuous mode */ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + /* disable scan mode */ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* disable ADC inserted channel group convert automatically */ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* disable ADC continuous mode */ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] data_alignment: data alignment select + only one parameter can be selected which is shown as below: + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + /* MSB alignment */ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + /* LSB alignment */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + /* enable ADC */ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + /* disable ADC */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + /* enable DMA request */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + /* disable DMA request */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular and inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel, the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + /* disable discontinuous mode of regular & inserted channel */ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC)); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + /* enable regular channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + /* enable inserted channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + /* disable discontinuous mode of regular & inserted channel */ + default: + break; + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the length of regular channel group */ + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + case ADC_INSERTED_CHANNEL: + /* configure the length of inserted channel group */ + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* configure ADC regular sequence */ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + /* the regular group sequence rank is smaller than six */ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * rank))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + /* the regular group sequence rank is smaller than twelve */ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_SIX)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_SIX))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + /* the regular group sequence rank is smaller than sixteen */ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_TWELVE)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_TWELVE))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + /* illegal parameters */ + } + + /* configure ADC sampling time */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the regular group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the regular group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + /* get inserted channel group length */ + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); + /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH - (inserted_length - rank) * ADC_INSERTED_CHANNEL_RANK_LENGTH))); + isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH - (inserted_length - rank) * ADC_INSERTED_CHANNEL_RANK_LENGTH)); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the inserted group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the inserted group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 + \param[in] offset: the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); + num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); + + if(num <= ADC_OFFSET_LENGTH){ + /* calculate the offset of the register */ + num = num * ADC_OFFSET_SHIFT_LENGTH; + /* configure the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select + \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11 + \arg ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select + \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select + \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure ADC regular group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + /* configure ADC inserted group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief configure ADC external trigger + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* external trigger enable for regular channel */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* external trigger enable for inserted channel */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* external trigger disable for regular channel */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* external trigger disable for inserted channel */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable regular group channel software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable inserted channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel: inserted channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + /* read the data of channel 0 */ + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + /* read the data of channel 1 */ + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + /* read the data of channel 2 */ + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + /* read the data of channel 3 */ + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + /* analog watchdog channel select */ + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* regular channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + /* inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* regular and inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] low_threshold: analog watchdog low threshold,0..4095 + \param[in] high_threshold: analog watchdog high threshold,0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected which are shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the ADC interrupt flag + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt bits + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + + return interrupt_flag; +} + +/*! + \brief clear the ADC interrupt flag + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* enable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + /* enable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + /* enable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* disable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + /* disable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + /* disable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} + + + +/*! + \brief configure ADC resolution + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] resolution: ADC resolution + only one among these parameters can be selected + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief configure ADC oversample mode + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] mode: ADC oversampling mode + only oneparameter can be selected + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger + \param[in] shift: ADC oversampling shift + only oneparameter can be selected + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only oneparameter can be selected + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio) +{ + /* configure ADC oversampling mode */ + if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; + }else{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + } + + /* configure the shift and ratio */ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); + ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c new file mode 100644 index 0000000000..26a5ab7892 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c @@ -0,0 +1,421 @@ +/*! + \file gd32f20x_bkp.c + \brief BKP driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_bkp.h" + +#define TAMPER0_FLAG_SHIFT ((uint8_t)8U) +#define TAMPER1_FLAG_SHIFT ((uint8_t)9U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number - 1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number - 1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_data_read(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number - 1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number - 1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + only one parameter can be selected which is shown as below: + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief select RTC clock output + \param[in] clocksel: RTC clock output selection + \arg RTC_CLOCK_DIV64: RTC clock div 64 + \arg RTC_CLOCK_DIV1: RTC clock + \param[out] none + \retval none +*/ +void bkp_rtc_clock_output_select(uint16_t clocksel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CCOSEL; + ctl |= clocksel; + BKP_OCTL = ctl; +} + +/*! + \brief RTC clock calibration direction + \param[in] direction: RTC clock calibration direction + \arg RTC_CLOCK_SLOWED_DOWN: RTC clock slow down + \arg RTC_CLOCK_SPEED_UP: RTC clock speed up + \param[out] none + \retval none +*/ +void bkp_rtc_clock_calibration_direction(uint16_t direction) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CALDIR; + ctl |= direction; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + /* configure BKP_OCTL_RCCV with value */ + ctl = BKP_OCTL; + ctl &= (uint16_t)OCTL_RCCV(0); + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCTL0 |= (uint16_t)BKP_TPCTL0_TPEN0; + }else{ + BKP_TPCTL1 |= (uint16_t)BKP_TPCTL1_TPEN1; + } +} + +/*! + \brief disable tamper detection + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCTL0 &= (uint16_t)~BKP_TPCTL0_TPEN0; + }else{ + BKP_TPCTL1 &= (uint16_t)~BKP_TPCTL1_TPEN1; + } +} + +/*! + \brief set tamper pin active level + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[in] level: tamper active level + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(bkp_tamper_enum tamperx, uint16_t level) +{ + uint16_t ctl = 0U; + + if(TAMPER_0 == tamperx){ + ctl = BKP_TPCTL0; + ctl &= (uint16_t)~BKP_TPCTL0_TPAL0; + ctl |= level; + BKP_TPCTL0 = ctl; + }else{ + ctl = BKP_TPCTL1; + ctl &= (uint16_t)~BKP_TPCTL1_TPAL1; + ctl |= level; + BKP_TPCTL1 = ctl; + } +} + +/*! + \brief enable tamper interrupt + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_enable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE0; + }else{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE1; + } +} + +/*! + \brief disable tamper interrupt + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_disable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE0; + }else{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE1; + } +} + +/*! + \brief waveform detect configure + \param[in] waveform_detect_mode + \arg BKP_WAVEFORM_DETECT_1: the first waveform detection + \arg BKP_WAVEFORM_DETECT_2: the second waveform detection + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval FlagStatus: SET or RESET +*/ +void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus newvalue) +{ + uint16_t tpctl0 = 0U, tpctl1 = 0U, octl = 0U; + + tpctl0 = BKP_TPCTL0; + tpctl1 = BKP_TPCTL1; + + /* disable tamper0 and tamper1 */ + tpctl0 &= (uint16_t)~BKP_TPCTL0_TPEN0; + tpctl1 &= (uint16_t)~BKP_TPCTL1_TPEN1; + + octl = BKP_OCTL; + + /* RTC clock output divided 64 */ + octl &= (uint16_t)~BKP_OCTL_CCOSEL; + + /* set the value to the register */ + BKP_TPCTL0 = tpctl0; + BKP_TPCTL1 = tpctl1; + BKP_OCTL = octl; + + if(DISABLE != newvalue){ + /* enable the waveform detection function */ + BKP_TPCTL1 |= waveform_detect_mode; + }else{ + /* disable the waveform detection function */ + BKP_TPCTL1 &= (uint16_t)(~waveform_detect_mode); + } +} + +/*! + \brief get bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER0: tamper0 event flag + \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/wavedetect event flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER0: tamper0 event flag + \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/wavedetect event flag + \param[out] none + \retval none +*/ +void bkp_flag_clear(uint16_t flag) +{ + if(BKP_FLAG_TAMPER0 == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER0_FLAG_SHIFT); + }else if(BKP_FLAG_TAMPER1_WAVEDETECT == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER1_FLAG_SHIFT); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief get bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER0: tamper0 interrupt flag + \arg BKP_INT_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER0: tamper0 interrupt flag + \arg BKP_INT_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect interrupt flag + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(uint16_t flag) +{ + if(BKP_INT_FLAG_TAMPER0 == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER0_FLAG_SHIFT); + }else if(BKP_INT_FLAG_TAMPER1_WAVEDETECT == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER1_FLAG_SHIFT); + }else{ + /* illegal parameters */ + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c new file mode 100644 index 0000000000..c9d321a6e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c @@ -0,0 +1,1035 @@ +/*! + \file gd32f20x_can.c + \brief CAN driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2019-11-27, V2.1.1, firmware for GD32F20x + \version 2020-07-14, V2.1.2, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_can.h" + +#define CAN_ERROR_HANDLE(s) do{}while(1) + +#define RFO1_CLEAR_VAL ((uint32_t)0x00000000U) /*!< RFO1 clear value */ +#define RFF1_CLEAR_VAL ((uint32_t)0x00000018U) /*!< RFF1 clear value */ + +/*! + \brief deinitialize CAN + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_deinit(uint32_t can_periph) +{ + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + }else{ + rcu_periph_reset_enable(RCU_CAN1RST); + rcu_periph_reset_disable(RCU_CAN1RST); + } +} + +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + +/*! + \brief initialize CAN + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init) +{ + uint32_t timeout = CAN_TIMEOUT; + ErrStatus flag = ERROR; + + /* disable sleep mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + /* enable initialize mode */ + CAN_CTL(can_periph) |= CAN_CTL_IWMOD; + /* wait ACK */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check initialize working success */ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + /* set the bit timing register */ + CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ + BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ + BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ + BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ + BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + /* time trigger communication mode */ + if(ENABLE == can_parameter_init->time_triggered){ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + } + /* automatic bus-off managment */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + CAN_CTL(can_periph) |= CAN_CTL_ABOR; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; + } + /* automatic wakeup mode */ + if(ENABLE == can_parameter_init->auto_wake_up){ + CAN_CTL(can_periph) |= CAN_CTL_AWU; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_AWU; + } + /* automatic retransmission mode disable*/ + if(ENABLE == can_parameter_init->no_auto_retrans){ + CAN_CTL(can_periph) |= CAN_CTL_ARD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite){ + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; + } + /* transmit fifo order */ + if(ENABLE == can_parameter_init->trans_fifo_order){ + CAN_CTL(can_periph) |= CAN_CTL_TFO; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TFO; + } + /* disable initialize mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; + timeout = CAN_TIMEOUT; + /* wait the ACK */ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check exit initialize mode */ + if(0U != timeout){ + flag = SUCCESS; + } + } + return flag; +} + +/*! + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +{ + uint32_t val = 0U; + + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* disable filter */ + CAN_FW(CAN0) &= ~(uint32_t)val; + + /* filter 16 bits */ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + /* set filter 16 bits */ + CAN_FSCFG(CAN0) &= ~(uint32_t)val; + /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + } + /* filter 32 bits */ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + /* set filter 32 bits */ + CAN_FSCFG(CAN0) |= (uint32_t)val; + /* 32 bits list or first 32 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* 32 bits mask or second 32 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + } + + /* filter mode */ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + /* mask mode */ + CAN_FMCFG(CAN0) &= ~(uint32_t)val; + }else{ + /* list mode */ + CAN_FMCFG(CAN0) |= (uint32_t)val; + } + + /* filter FIFO */ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + /* FIFO0 */ + CAN_FAFIFO(CAN0) &= ~(uint32_t)val; + }else{ + /* FIFO1 */ + CAN_FAFIFO(CAN0) |= (uint32_t)val; + } + + /* filter working */ + if(ENABLE == can_filter_parameter_init->filter_enable){ + + CAN_FW(CAN0) |= (uint32_t)val; + } + + /* filter lock enable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief set CAN1 fliter start bank number + \param[in] start_bank: CAN1 start bank number + only one parameter can be selected which is shown as below: + \arg (1..27) + \param[out] none + \retval none +*/ +void can1_filter_start_bank(uint8_t start_bank) +{ + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* set CAN1 filter start number */ + CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; + CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); + /* filter lock enaable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief enable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_debug_freeze_enable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) |= CAN_CTL_DFZ; + + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + }else{ + dbg_periph_enable(DBG_CAN1_HOLD); + } +} + +/*! + \brief disable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_debug_freeze_disable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; + + if(CAN0 == can_periph){ + dbg_periph_disable(DBG_CAN0_HOLD); + }else{ + dbg_periph_disable(DBG_CAN1_HOLD); + } +} + +/*! + \brief enable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_time_trigger_mode_enable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* enable the tcc mode */ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + /* enable time stamp */ + for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; + } +} + +/*! + \brief disable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_time_trigger_mode_disable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* disable the TCC mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + /* reset TSEN bits */ + for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; + } +} + +/*! + \brief transmit CAN message + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF + \param[out] none + \retval mailbox_number +*/ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +{ + uint8_t mailbox_number = CAN_MAILBOX0; + + /* select one empty mailbox */ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + mailbox_number = CAN_MAILBOX0; + }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + mailbox_number = CAN_MAILBOX1; + }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + mailbox_number = CAN_MAILBOX2; + }else{ + mailbox_number = CAN_NOMAILBOX; + } + /* return no mailbox empty */ + if(CAN_NOMAILBOX == mailbox_number){ + return CAN_NOMAILBOX; + } + + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; + if(CAN_FF_STANDARD == transmit_message->tx_ff){ + /* set transmit mailbox standard identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ + transmit_message->tx_ft); + }else{ + /* set transmit mailbox extended identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ + transmit_message->tx_ff | \ + transmit_message->tx_ft); + } + /* set the data length */ + CAN_TMP(can_periph, mailbox_number) &= ((uint32_t)~CAN_TMP_DLENC); + CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; + /* set the data */ + CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); + CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); + /* enable transmission */ + CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; + + return mailbox_number; +} + +/*! + \brief get CAN transmit state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOX(x=0,1,2) + \param[out] none + \retval can_transmit_state_enum +*/ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) +{ + can_transmit_state_enum state = CAN_TRANSMIT_FAILED; + uint32_t val = 0U; + + /* check selected mailbox state */ + switch(mailbox_number){ + /* mailbox0 */ + case CAN_MAILBOX0: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); + break; + /* mailbox1 */ + case CAN_MAILBOX1: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); + break; + /* mailbox2 */ + case CAN_MAILBOX2: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); + break; + default: + val = CAN_TRANSMIT_FAILED; + break; + } + + switch(val){ + /* transmit pending */ + case (CAN_STATE_PENDING): + state = CAN_TRANSMIT_PENDING; + break; + /* mailbox0 transmit succeeded */ + case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + state = CAN_TRANSMIT_OK; + break; + /* mailbox1 transmit succeeded */ + case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + state = CAN_TRANSMIT_OK; + break; + /* mailbox2 transmit succeeded */ + case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + state = CAN_TRANSMIT_OK; + break; + /* transmit failed */ + default: + state = CAN_TRANSMIT_FAILED; + break; + } + return state; +} + +/*! + \brief stop CAN transmission + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOXx(x=0,1,2) + \param[out] none + \retval none +*/ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) +{ + if(CAN_MAILBOX0 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } + }else if(CAN_MAILBOX1 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } + }else if(CAN_MAILBOX2 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } + }else{ + /* illegal parameters */ + } +} + +/*! + \brief CAN receive message + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] fifo_number + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 + \retval none +*/ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +{ + /* get the frame format */ + receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); + if(CAN_FF_STANDARD == receive_message->rx_ff){ + /* get standard identifier */ + receive_message -> rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + }else{ + /* get extended identifier */ + receive_message -> rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + } + + /* get frame type */ + receive_message -> rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); + /* get recevie data length */ + receive_message -> rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + /* filtering index */ + receive_message -> rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + + /* receive data */ + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + + /* release FIFO */ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else{ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + } +} + +/*! + \brief release FIFO0 + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval none +*/ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) +{ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else if(CAN_FIFO1 == fifo_number){ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + }else{ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); + } +} + +/*! + \brief CAN receive message length + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval message length +*/ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) +{ + uint8_t val = 0U; + + if(CAN_FIFO0 == fifo_number){ + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); + }else{ + /* illegal parameters */ + } + return val; +} + +/*! + \brief set CAN working mode + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] can_working_mode + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) +{ + ErrStatus flag = ERROR; + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode){ + /* disable sleep mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); + /* set initialize mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; + /* wait the acknowledge */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_NORMAL == working_mode){ + /* enter normal mode */ + CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); + /* wait the acknowledge */ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + timeout--; + } + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_SLEEP == working_mode){ + /* disable initialize mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); + /* set sleep mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; + /* wait the acknowledge */ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else{ + flag = ERROR; + } + return flag; +} + +/*! + \brief wake up CAN + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_wakeup(uint32_t can_periph) +{ + ErrStatus flag = ERROR; + uint32_t timeout = CAN_TIMEOUT; + + /* wakeup */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + timeout--; + } + /* check state */ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + return flag; +} + +/*! + \brief get CAN error type + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure +*/ +can_error_enum can_error_get(uint32_t can_periph) +{ + can_error_enum error; + error = CAN_ERROR_NONE; + + /* get error type */ + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); + return error; +} + +/*! + \brief get CAN receive error number + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval error number +*/ +uint8_t can_receive_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief get CAN transmit error number + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval error number +*/ +uint8_t can_transmit_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WAKEUP: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WAKEUP: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + +/*! + \brief get CAN flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) +{ + /* get flag and interrupt enable state */ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \param[out] none + \retval none +*/ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag) +{ + if (flag == CAN_FLAG_RFO1){ + CAN_REG_VAL(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_FLAG_RFF1){ + CAN_REG_VAL(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); + } +} + +/*! + \brief get CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFL0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFL1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); + } + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \param[out] none + \retval none +*/ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + if (flag == CAN_INT_FLAG_RFO1){ + CAN_REG_VALS(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_INT_FLAG_RFF1){ + CAN_REG_VALS(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c new file mode 100644 index 0000000000..e985e0b5ff --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c @@ -0,0 +1,388 @@ +/*! + \file gd32f20x_cau.c + \brief CAU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" +#include "gd32f20x_rcu.h" + +#define FLAG_MASK ((uint32_t)0x00000020U) + +/*! + \brief reset the CAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void cau_deinit(void) +{ + /* enable CAU reset state */ + rcu_periph_reset_enable(RCU_CAURST); + /* release CAU from reset state */ + rcu_periph_reset_disable(RCU_CAURST); +} + +/*! + \brief enable the CAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void cau_enable(void) +{ + /* enable the CAU processor */ + CAU_CTL |= CAU_CTL_CAUEN; +} + +/*! + \brief disable the CAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void cau_disable(void) +{ + /* disable the CAU processor */ + CAU_CTL &= ~CAU_CTL_CAUEN; +} + +/*! + \brief enable the CAU DMA interface + \param[in] dma_req: specify the CAU DMA transfer request to be enabled + one or more parameters can be selected which are shown as below + \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer + \arg CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer + \param[out] none + \retval none +*/ +void cau_dma_enable(uint32_t dma_req) +{ + /* enable the selected CAU DMA request */ + CAU_DMAEN |= dma_req; +} + +/*! + \brief disable the CAU DMA interface + \param[in] dma_req: specify the CAU DMA transfer request to be disabled + one or more parameters can be selected which are shown as below + \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer + \arg CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer + \param[out] none + \retval none +*/ +void cau_dma_disable(uint32_t dma_req) +{ + /* disable the selected CAU DMA request */ + CAU_DMAEN &= ~(dma_req); +} + +/*! + \brief initialize the CAU peripheral + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] algo_mode: algorithm mode selection + only one parameter can be selected which is shown as below + \arg CAU_MODE_TDES_ECB: TDES-ECB (3DES Electronic codebook) + \arg CAU_MODE_TDES_CBC: TDES-CBC (3DES Cipher block chaining) + \arg CAU_MODE_DES_ECB: DES-ECB (simple DES Electronic codebook) + \arg CAU_MODE_DES_CBC: DES-CBC (simple DES Cipher block chaining) + \arg CAU_MODE_AES_ECB: AES-ECB (AES Electronic codebook) + \arg CAU_MODE_AES_CBC: AES-CBC (AES Cipher block chaining) + \arg CAU_MODE_AES_CTR: AES-CTR (AES counter mode) + \arg CAU_MODE_AES_KEY: AES decryption key preparation mode + \param[in] swapping: data swapping selection + only one parameter can be selected which is shown as below + \arg CAU_SWAPPING_32BIT: no swapping + \arg CAU_SWAPPING_16BIT: half-word swapping + \arg CAU_SWAPPING_8BIT: bytes swapping + \arg CAU_SWAPPING_1BIT: bit swapping + \param[out] none + \retval none +*/ +void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping) +{ + /* select algorithm mode */ + CAU_CTL &= ~CAU_CTL_ALGM; + CAU_CTL |= algo_mode; + + /* select data swapping */ + CAU_CTL &= ~CAU_CTL_DATAM; + CAU_CTL |= swapping; + + /* select algorithm direction */ + CAU_CTL &= ~CAU_CTL_CAUDIR; + CAU_CTL |= algo_dir; +} + +/*! + \brief configure key size if used AES algorithm + \param[in] key_size: key length selection when aes mode + only one parameter can be selected which is shown as below + \arg CAU_KEYSIZE_128BIT: 128 bit key length + \arg CAU_KEYSIZE_192BIT: 192 bit key length + \arg CAU_KEYSIZE_256BIT: 256 bit key length + \param[out] none + \retval none +*/ +void cau_aes_keysize_config(uint32_t key_size) +{ + CAU_CTL &= ~CAU_CTL_KEYM; + CAU_CTL |= key_size; +} + +/*! + \brief initialize the key parameters + \param[in] key_initpara: key init parameter struct + key_0_high: key 0 high + key_0_low: key 0 low + key_1_high: key 1 high + key_1_low: key 1 low + key_2_high: key 2 high + key_2_low: key 2 low + key_3_high: key 3 high + key_3_low: key 3 low + \param[out] none + \retval none +*/ +void cau_key_init(cau_key_parameter_struct* key_initpara) +{ + CAU_KEY0H = key_initpara->key_0_high; + CAU_KEY0L = key_initpara->key_0_low; + CAU_KEY1H = key_initpara->key_1_high; + CAU_KEY1L = key_initpara->key_1_low; + CAU_KEY2H = key_initpara->key_2_high; + CAU_KEY2L = key_initpara->key_2_low; + CAU_KEY3H = key_initpara->key_3_high; + CAU_KEY3L = key_initpara->key_3_low; +} + +/*! + \brief initialize the sturct cau_key_initpara + \param[in] key_initpara: key init parameter struct + key_0_high: key 0 high + key_0_low: key 0 low + key_1_high: key 1 high + key_1_low: key 1 low + key_2_high: key 2 high + key_2_low: key 2 low + key_3_high: key 3 high + key_3_low: key 3 low + \param[out] none + \retval none +*/ +void cau_key_parameter_init(cau_key_parameter_struct* key_initpara) +{ + key_initpara->key_0_high = 0U; + key_initpara->key_0_low = 0U; + key_initpara->key_1_high = 0U; + key_initpara->key_1_low = 0U; + key_initpara->key_2_high = 0U; + key_initpara->key_2_low = 0U; + key_initpara->key_3_high = 0U; + key_initpara->key_3_low = 0U; +} + +/*! + \brief initialize the vectors parameters + \param[in] iv_initpara: vectors init parameter struct + iv_0_high: init vector 0 high + iv_0_low: init vector 0 low + iv_1_high: init vector 1 high + iv_1_low: init vector 1 low + \param[out] none + \retval none +*/ +void cau_iv_init(cau_iv_parameter_struct* iv_initpara) +{ + CAU_IV0H = iv_initpara->iv_0_high; + CAU_IV0L = iv_initpara->iv_0_low; + CAU_IV1H = iv_initpara->iv_1_high; + CAU_IV1L = iv_initpara->iv_1_low; +} + +/*! + \brief initialize the vectors parameters + \param[in] iv_initpara: vectors init parameter struct + iv_0_high: init vector 0 high + iv_0_low: init vector 0 low + iv_1_high: init vector 1 high + iv_1_low: init vector 1 low + \param[out] none + \retval none +*/ +void cau_iv_parameter_init(cau_iv_parameter_struct* iv_initpara) +{ + iv_initpara->iv_0_high = 0U; + iv_initpara->iv_0_low = 0U; + iv_initpara->iv_1_high = 0U; + iv_initpara->iv_1_low = 0U; +} + +/*! + \brief flush the IN and OUT FIFOs + \param[in] none + \param[out] none + \retval none +*/ +void cau_fifo_flush(void) +{ + /* reset the read and write pointers of the FIFOs */ + CAU_CTL |= CAU_CTL_FFLUSH; +} + +/*! + \brief return whether CAU peripheral is enabled or disabled + \param[in] none + \param[out] none + \retval ControlStatus: ENABLE or DISABLE +*/ +ControlStatus cau_enable_state_get(void) +{ + ControlStatus ret = DISABLE; + if(RESET != (CAU_CTL & CAU_CTL_CAUEN)){ + ret = ENABLE; + } + return ret; +} + +/*! + \brief write data to the IN FIFO + \param[in] data: data to write + \param[out] none + \retval none +*/ +void cau_data_write(uint32_t data) +{ + CAU_DI = data; +} + +/*! + \brief return the last data entered into the output FIFO + \param[in] none + \param[out] none + \retval last data entered into the output FIFO +*/ +uint32_t cau_data_read(void) +{ + return CAU_DO; +} + +/*! + \brief get the CAU flag status + \param[in] flag: CAU flag status + only one parameter can be selected which is shown as below + \arg CAU_FLAG_INFIFO_EMPTY: input FIFO empty + \arg CAU_FLAG_INFIFO_NO_FULL: input FIFO is not full + \arg CAU_FLAG_OUTFIFO_NO_EMPTY: output FIFO not empty + \arg CAU_FLAG_OUTFIFO_FULL: output FIFO is full + \arg CAU_FLAG_BUSY: the CAU core is busy + \arg CAU_FLAG_INFIFO: input FIFO flag status + \arg CAU_FLAG_OUTFIFO: output FIFO flag status + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus cau_flag_get(uint32_t flag) +{ + uint32_t reg = 0U; + FlagStatus ret_flag = RESET; + + /* check if the flag is in CAU_STAT1 register */ + if(RESET != (flag & FLAG_MASK)){ + reg = CAU_STAT1; + }else{ + /* the flag is in CAU_STAT0 register */ + reg = CAU_STAT0; + } + + /* check the status of the specified CAU flag */ + if(RESET != (reg & flag)){ + ret_flag = SET; + } + + return ret_flag; +} + +/*! + \brief enable the CAU interrupts + \param[in] interrupt: specify the CAU interrupt source to be enabled + one or more parameters can be selected which are shown as below + \arg CAU_INT_INFIFO: input FIFO interrupt + \arg CAU_INT_OUTFIFO: output FIFO interrupt + \param[out] none + \retval none +*/ +void cau_interrupt_enable(uint32_t interrupt) +{ + /* enable the selected CAU interrupt */ + CAU_INTEN |= interrupt; +} + +/*! + \brief disable the CAU interrupts + \param[in] interrupt: specify the CAU interrupt source to be disabled + one or more parameters can be selected which are shown as below + \arg CAU_INT_INFIFO: input FIFO interrupt + \arg CAU_INT_OUTFIFO: output FIFO interrupt + \param[out] none + \retval none +*/ +void cau_interrupt_disable(uint32_t interrupt) +{ + /* disable the selected CAU interrupt */ + CAU_INTEN &= ~(interrupt); +} + +/*! + \brief get the interrupt flag + \param[in] int_flag: CAU interrupt flag + only one parameter can be selected which is shown as below + \arg CAU_INT_FLAG_INFIFO: input FIFO interrupt + \arg CAU_INT_FLAG_OUTFIFO: output FIFO interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus cau_interrupt_flag_get(uint32_t int_flag) +{ + FlagStatus flag = RESET; + + /* check the status of the specified CAU interrupt */ + if(RESET != (CAU_INTF & int_flag)){ + flag = SET; + } + + return flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c new file mode 100644 index 0000000000..5b7429a54c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c @@ -0,0 +1,372 @@ +/*! + \file gd32f20x_cau_aes.c + \brief CAU_AES driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" + +#define AESBSY_TIMEOUT ((uint32_t)0x00010000U) + +/* AES key structure parameter config */ +static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct* cau_key_initpara); +/* AES calculate process */ +static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief encrypt and decrypt using AES in ECB mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 16 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_aes_ecb(uint32_t algo_dir, uint8_t *key, uint16_t keysize, cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* AES key structure parameter config */ + cau_aes_key_config(key, keysize, &key_initpara); + /* key initialization */ + cau_key_init(&key_initpara); + + /* AES decryption */ + if(CAU_DECRYPT == algo_dir){ + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + /* initialize the CAU peripheral */ + cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); + + /* enable the CAU peripheral */ + cau_enable(); + + /* wait until the busy flag is RESET */ + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + } + } + + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_AES_ECB, CAU_SWAPPING_8BIT); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* AES calculate process */ + ret = cau_aes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using AES in CBC mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 16 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* AES key structure parameter config */ + cau_aes_key_config(key, keysize, &key_initpara); + /* key initialization */ + cau_key_init(&key_initpara); + + /* AES decryption */ + if(CAU_DECRYPT == algo_dir){ + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + /* initialize the CAU peripheral */ + cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); + + /* enable the CAU peripheral */ + cau_enable(); + + /* wait until the busy flag is RESET */ + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + } + } + + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_AES_CBC, CAU_SWAPPING_8BIT); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_low = __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* AES calculate process */ + ret = cau_aes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using AES in CTR mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 16 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_AES_CTR, CAU_SWAPPING_8BIT); + + /* AES key structure parameter config */ + cau_aes_key_config(key, keysize, &key_initpara); + /* key initialization */ + cau_key_init(&key_initpara); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_low = __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* AES calculate process */ + ret = cau_aes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief AES key structure parameter config + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[out] cau_key_initpara: key init parameter struct + key_0_high: key 0 high + key_0_low: key 0 low + key_1_high: key 1 high + key_1_low: key 1 low + key_2_high: key 2 high + key_2_low: key 2 low + key_3_high: key 3 high + key_3_low: key 3 low + \retval none +*/ +static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct* cau_key_initpara) +{ + uint32_t keyaddr = (uint32_t)key; + + switch(keysize){ + case 128: + cau_aes_keysize_config(CAU_KEYSIZE_128BIT); + cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + break; + case 192: + cau_aes_keysize_config(CAU_KEYSIZE_192BIT); + cau_key_initpara->key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_1_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + break; + case 256: + cau_aes_keysize_config(CAU_KEYSIZE_256BIT); + cau_key_initpara->key_0_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_0_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_1_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + break; + default: + break; + } +} + +/*! + \brief AES calculate process + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 16 + \param[in] output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output) +{ + uint32_t inputaddr = (uint32_t)input; + uint32_t outputaddr = (uint32_t)output; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()){ + return ERROR; + } + + for(i = 0U; i < in_length; i += 16U){ + /* write data to the IN FIFO */ + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + + /* wait until the complete message has been processed */ + counter = 0U; + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the output block from the output FIFO */ + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + } + } + + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c new file mode 100644 index 0000000000..90cc93cd42 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c @@ -0,0 +1,191 @@ +/*! + \file gd32f20x_cau_des.c + \brief CAU_DES driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" + +#define DESBUSY_TIMEOUT ((uint32_t)0x00010000U) + +/* DES calculate process */ +static ErrStatus cau_des_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief encrypt and decrypt using DES in ECB mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for DES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + + uint32_t keyaddr = (uint32_t)key; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_DES_ECB, CAU_SWAPPING_8BIT); + + /* key initialisation */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(& key_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* DES calculate process */ + ret = cau_des_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using DES in CBC mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for DES algorithm + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_des_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + + uint32_t keyaddr = (uint32_t)key; + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_DES_CBC, CAU_SWAPPING_8BIT); + + /* key initialisation */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(&key_initpara); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low= __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* DES calculate process */ + ret = cau_des_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief DES calculate process + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 8 + \param[in] output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus cau_des_calculate(uint8_t *input, uint32_t in_length, uint8_t *output) +{ + uint32_t inputaddr = (uint32_t)input; + uint32_t outputaddr = (uint32_t)output; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()){ + return ERROR; + } + + for(i = 0U; i < in_length; i += 8U){ + /* write data to the IN FIFO */ + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + + /* wait until the complete message has been processed */ + counter = 0U; + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((DESBUSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the output block from the output FIFO */ + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + } + } + + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c new file mode 100644 index 0000000000..07af6c81df --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c @@ -0,0 +1,207 @@ +/*! + \file gd32f20x_cau_tdes.c + \brief CAU_TDES driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" + +#define TDESBSY_TIMEOUT ((uint32_t)0x00010000U) + +/* TDES calculate process */ +static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief encrypt and decrypt using TDES in ECB mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + + uint32_t keyaddr = (uint32_t)key; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_TDES_ECB, CAU_SWAPPING_8BIT); + + /* key initialization */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(&key_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* TDES calculate process */ + ret = cau_tdes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using TDES in CBC mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for TDES algorithm + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + + uint32_t keyaddr = (uint32_t)key; + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_TDES_CBC, CAU_SWAPPING_8BIT); + + /* key initialization */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(&key_initpara); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low= __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* TDES calculate process */ + ret = cau_tdes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief TDES calculate process + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 8 + \param[in] output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output) +{ + uint32_t inputaddr = (uint32_t)input; + uint32_t outputaddr = (uint32_t)output; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()){ + return ERROR; + } + + for(i = 0U; i < in_length; i += 8U){ + /* write data to the IN FIFO */ + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + + /* wait until the complete message has been processed */ + counter = 0U; + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((TDESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the output block from the output FIFO */ + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + } + } + + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c new file mode 100644 index 0000000000..5fc9b2e86f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c @@ -0,0 +1,130 @@ +/*! + \file gd32f20x_crc.c + \brief CRC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register to the value of initializaiton data register + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specify 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = array[index]; + } + return (CRC_DATA); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c new file mode 100644 index 0000000000..5eb5bd974b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c @@ -0,0 +1,557 @@ +/*! + \file gd32f20x_dac.c + \brief DAC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dac.h" + +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + +/*! + \brief deinitialize DAC + \param[in] none + \param[out] none + \retval none +*/ +void dac_deinit(void) +{ + rcu_periph_reset_enable(RCU_DACRST); + rcu_periph_reset_disable(RCU_DACRST); +} + +/*! + \brief enable DAC + \param[in] dac_periph + \arg DACx(x =0,1) + \param[out] none + \retval none +*/ +void dac_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DEN0; + }else{ + DAC_CTL |= DAC_CTL_DEN1; + } +} + +/*! + \brief disable DAC + \param[in] dac_periph + \arg DACx(x =0,1) + \param[out] none + \retval none +*/ +void dac_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DEN1; + } +} + +/*! + \brief enable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DDMAEN0; + }else{ + DAC_CTL |= DAC_CTL_DDMAEN1; + } +} + +/*! + \brief disable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDMAEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DDMAEN1; + } +} + +/*! + \brief enable DAC output buffer + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DBOFF0; + }else{ + DAC_CTL &= ~DAC_CTL_DBOFF1; + } +} + +/*! + \brief disable DAC output buffer + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DBOFF0; + }else{ + DAC_CTL |= DAC_CTL_DBOFF1; + } +} + +/*! + \brief get DAC output value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + +/*! + \brief enable DAC trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DTEN0; + }else{ + DAC_CTL |= DAC_CTL_DTEN1; + } +} + +/*! + \brief disable DAC trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DTEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DTEN1; + } +} + +/*! + \brief set DAC trigger source + \param[in] dac_periph + \arg DACx(x =0,1) + \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: + \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO + \arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO + \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO + \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO + \arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO + \arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO + \arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event + \arg DAC_TRIGGER_SOFTWARE: software trigger + \param[out] none + \retval none +*/ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL0; + DAC_CTL |= triggersource; + }else{ + /* configure DAC1 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL1; + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; + } +} + +/*! + \brief configure DAC wave mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] wave_mode + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_DISABLE: wave disable + \arg DAC_WAVE_MODE_LFSR: LFSR noise mode + \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode + \param[out] none + \retval none +*/ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM0; + DAC_CTL |= wave_mode; + }else{ + /* configure DAC1 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM1; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC wave bit width + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] bit_width + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 + \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 + \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 + \arg DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4 + \arg DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5 + \arg DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6 + \arg DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7 + \arg DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8 + \arg DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9 + \arg DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10 + \arg DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11 + \arg DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12 + \param[out] none + \retval none +*/ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= bit_width; + }else{ + /* configure DAC1 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC LFSR noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] unmask_bits + only one parameter can be selected which is shown as below: + \arg DAC_LFSR_BIT0: unmask the LFSR bit0 + \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] + \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] + \arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0] + \arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0] + \arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0] + \arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0] + \arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0] + \arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0] + \arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0] + \arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0] + \arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0] + \param[out] none + \retval none +*/ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= unmask_bits; + }else{ + /* configure DAC1 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC triangle noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] amplitude + only one parameter can be selected which is shown as below: + \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 + \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 + \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 + \arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15 + \arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31 + \arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63 + \arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127 + \arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255 + \arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511 + \arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023 + \arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047 + \arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095 + \param[out] none + \retval none +*/ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= amplitude; + }else{ + /* configure DAC1 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL |= (ctl); +} + +/*! + \brief disable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL &= (~ctl); +} + +/*! + \brief enable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_enable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT |= (swt); +} + +/*! + \brief disable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_disable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT &= (~swt); +} + +/*! + \brief enable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL &= (~ctl); +} + +/*! + \brief disable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL |= (ctl); +} + +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c new file mode 100644 index 0000000000..f849106dac --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c @@ -0,0 +1,152 @@ +/*! + \file gd32f20x_dbg.c + \brief DBG driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dbg.h" + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_CTL |= (uint32_t)dbg_periph; +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_CTL &= ~(uint32_t)dbg_periph; +} + +/*! + \brief enable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_enable(void) +{ + DBG_CTL |= DBG_CTL_TRACE_IOEN; +} + +/*! + \brief disable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_disable(void) +{ + DBG_CTL &= ~DBG_CTL_TRACE_IOEN; +} + +/*! + \brief trace pin mode selection + \param[in] trace_mode: + only one parameter can be selected which is shown as below: + \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 + \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 + \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 + \param[out] none + \retval none +*/ +void dbg_trace_pin_mode_set(uint32_t trace_mode) +{ + DBG_CTL &= ~DBG_CTL_TRACE_MODE; + DBG_CTL |= trace_mode; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c new file mode 100644 index 0000000000..8417460ad7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c @@ -0,0 +1,344 @@ +/*! + \file gd32f20x_dci.c + \brief DCI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dci.h" + +/*! + \brief DCI deinit + \param[in] none + \param[out] none + \retval none +*/ +void dci_deinit(void) +{ + rcu_periph_reset_enable(RCU_DCIRST); + rcu_periph_reset_disable(RCU_DCIRST); +} + +/*! + \brief initialize DCI registers + \param[in] dci_struct: DCI parameter initialization structure + members of the structure and the member values are shown as below: + capture_mode : DCI_CAPTURE_MODE_CONTINUOUS, DCI_CAPTURE_MODE_SNAPSHOT + colck_polarity : DCI_CK_POLARITY_FALLING, DCI_CK_POLARITY_RISING + hsync_polarity : DCI_HSYNC_POLARITY_LOW, DCI_HSYNC_POLARITY_HIGH + vsync_polarity : DCI_VSYNC_POLARITY_LOW, DCI_VSYNC_POLARITY_HIGH + frame_rate : DCI_FRAME_RATE_ALL, DCI_FRAME_RATE_1_2, DCI_FRAME_RATE_1_4 + interface_format: DCI_INTERFACE_FORMAT_8BITS, DCI_INTERFACE_FORMAT_10BITS, + DCI_INTERFACE_FORMAT_12BITS, DCI_INTERFACE_FORMAT_14BITS + \param[out] none + \retval none +*/ +void dci_init(dci_parameter_struct* dci_struct) +{ + uint32_t reg = 0U; + /* disable capture function and DCI */ + DCI_CTL &= ~(DCI_CTL_CAP | DCI_CTL_DCIEN); + /* configure DCI parameter */ + reg |= dci_struct->capture_mode; + reg |= dci_struct->clock_polarity; + reg |= dci_struct->hsync_polarity; + reg |= dci_struct->vsync_polarity; + reg |= dci_struct->frame_rate; + reg |= dci_struct->interface_format; + + DCI_CTL = reg; +} + +/*! + \brief enable DCI function + \param[in] none + \param[out] none + \retval none +*/ +void dci_enable(void) +{ + DCI_CTL |= DCI_CTL_DCIEN; +} + +/*! + \brief disable DCI function + \param[in] none + \param[out] none + \retval none +*/ +void dci_disable(void) +{ + DCI_CTL &= ~DCI_CTL_DCIEN; +} + +/*! + \brief enable DCI capture + \param[in] none + \param[out] none + \retval none +*/ +void dci_capture_enable(void) +{ + DCI_CTL |= DCI_CTL_CAP; +} + +/*! + \brief disable DCI capture + \param[in] none + \param[out] none + \retval none +*/ +void dci_capture_disable(void) +{ + DCI_CTL &= ~DCI_CTL_CAP; +} + +/*! + \brief enable DCI jpeg mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_jpeg_enable(void) +{ + DCI_CTL |= DCI_CTL_JM; +} + +/*! + \brief disable DCI jpeg mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_jpeg_disable(void) +{ + DCI_CTL &= ~DCI_CTL_JM; +} + +/*! + \brief enable cropping window function + \param[in] none + \param[out] none + \retval none +*/ +void dci_crop_window_enable(void) +{ + DCI_CTL |= DCI_CTL_WDEN; +} + +/*! + \brief disable cropping window function + \param[in] none + \param[out] none + \retval none +*/ +void dci_crop_window_disable(void) +{ + DCI_CTL &= ~DCI_CTL_WDEN; +} + +/*! + \brief configure DCI cropping window + \param[in] start_x: window horizontal start position + \param[in] start_y: window vertical start position + \param[in] size_width: window horizontal size + \param[in] size_height: window vertical size + \param[out] none + \retval none +*/ +void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height) +{ + DCI_CWSPOS = ((uint32_t)start_x | ((uint32_t)start_y<<16)); + DCI_CWSZ = ((uint32_t)size_width | ((uint32_t)size_height<<16)); +} + +/*! + \brief enable embedded synchronous mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_embedded_sync_enable(void) +{ + DCI_CTL |= DCI_CTL_ESM; +} + +/*! + \brief disble embedded synchronous mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_embedded_sync_disable(void) +{ + DCI_CTL &= ~DCI_CTL_ESM; +} +/*! + \brief config synchronous codes in embedded synchronous mode + \param[in] frame_start: frame start code in embedded synchronous mode + \param[in] line_start: line start code in embedded synchronous mode + \param[in] line_end: line end code in embedded synchronous mode + \param[in] frame_end: frame end code in embedded synchronous mode + \param[out] none + \retval none +*/ +void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) +{ + DCI_SC = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); +} + +/*! + \brief config synchronous codes unmask in embedded synchronous mode + \param[in] frame_start: frame start code unmask bits in embedded synchronous mode + \param[in] line_start: line start code unmask bits in embedded synchronous mode + \param[in] line_end: line end code unmask bits in embedded synchronous mode + \param[in] frame_end: frame end code unmask bits in embedded synchronous mode + \param[out] none + \retval none +*/ +void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) +{ + DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); +} + +/*! + \brief read DCI data register + \param[in] none + \param[out] none + \retval data +*/ +uint32_t dci_data_read(void) +{ + return DCI_DATA; +} + +/*! + \brief get specified flag + \param[in] flag: + \arg DCI_FLAG_HS: HS line status + \arg DCI_FLAG_VS: VS line status + \arg DCI_FLAG_FV:FIFO valid + \arg DCI_FLAG_EF: end of frame flag + \arg DCI_FLAG_OVR: FIFO overrun flag + \arg DCI_FLAG_ESE: embedded synchronous error flag + \arg DCI_FLAG_VSYNC: vsync flag + \arg DCI_FLAG_EL: end of line flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dci_flag_get(uint32_t flag) +{ + uint32_t stat = 0U; + + if(flag >> 31){ + /* get flag status from DCI_STAT1 register */ + stat = DCI_STAT1; + }else{ + /* get flag status from DCI_STAT0 register */ + stat = DCI_STAT0; + } + + if(flag & stat){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief enable specified DCI interrupt + \param[in] interrupt: + \arg DCI_INT_EF: end of frame interrupt + \arg DCI_INT_OVR: FIFO overrun interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt + \arg DCI_INT_EL: end of line interrupt + \param[out] none + \retval none +*/ +void dci_interrupt_enable(uint32_t interrupt) +{ + DCI_INTEN |= interrupt; +} + +/*! + \brief disable specified DCI interrupt + \param[in] interrupt: + \arg DCI_INT_EF: end of frame interrupt + \arg DCI_INT_OVR: FIFO overrun interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt + \arg DCI_INT_EL: end of line interrupt + \param[out] none + \retval none +*/ +void dci_interrupt_disable(uint32_t interrupt) +{ + DCI_INTEN &= ~interrupt; +} + +/*! + \brief get specified interrupt flag + \param[in] int_flag: + \arg DCI_INT_FLAG_EF: end of frame interrupt flag + \arg DCI_INT_FLAG_OVR: FIFO overrun interrupt flag + \arg DCI_INT_FLAG_ESE: embedded synchronous error interrupt flag + \arg DCI_INT_FLAG_VSYNC: vsync interrupt flag + \arg DCI_INT_FLAG_EL: end of line interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dci_interrupt_flag_get(uint32_t int_flag) +{ + if(RESET == (DCI_INTF & int_flag)){ + return RESET; + }else{ + return SET; + } +} + +/*! + \brief clear specified interrupt flag + \param[in] int_flag: + \arg DCI_INT_EF: end of frame interrupt + \arg DCI_INT_OVR: FIFO overrun interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt + \arg DCI_INT_EL: end of line interrupt + \param[out] none + \retval none +*/ +void dci_interrupt_flag_clear(uint32_t int_flag) +{ + DCI_INTC |= int_flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c new file mode 100644 index 0000000000..5795341fa4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c @@ -0,0 +1,658 @@ +/*! + \file gd32f20x_dma.c + \brief DMA driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dma.h" +#include "gd32f20x_rcu.h" + +#define DMA_WRONG_HANDLE while(1){} + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + /* disable DMA channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); + + if((DMA1 == dma_periph) && (DMA_CH5 == channelx)){ + DMA_ACFG = DMA_ACFG_RESET_VALUE; + } +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct) +{ + uint32_t ctl; + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width, */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] number: the number of remaining data to be transferred by the DMA + \arg 0x0000-0xFFFF + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) +{ + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + /* check whether the flag is set or not */ + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear the flag of a DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + uint32_t gif_check = 0x0FU, gif_enable = 0x0EU; + + switch(flag){ + case DMA_INT_FLAG_FTF: + /* check whether the full transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + /* check whether the half transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + /* check whether the error interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + case DMA_INT_FLAG_G: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(gif_check, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & gif_enable; + break; + default: + DMA_WRONG_HANDLE + } + + /* when the interrupt flag is set and enabled, return SET */ + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief enable the DMA1 channel 5 Full_Data transfer mode + \param[in] none + \param[out] none + \retval none +*/ +void dma_1_channel_5_fulldata_transfer_enable(void) +{ + DMA_ACFG |= DMA_ACFG_FD_CH5EN; +} + +/*! + \brief disable the DMA1 channel 5 Full_Data transfer mode + \param[in] none + \param[out] none + \retval none +*/ +void dma_1_channel_5_fulldata_transfer_disable(void) +{ + DMA_ACFG &= ~DMA_ACFG_FD_CH5EN; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c new file mode 100644 index 0000000000..90d47a3f69 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c @@ -0,0 +1,3079 @@ +/*! + \file gd32f20x_enet.c + \brief ENET driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_enet.h" + +#ifdef GD32F20X_CL + +#if defined (__CC_ARM) /*!< ARM compiler */ +__align(4) +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +__align(4) +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +__align(4) +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +__align(4) +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined ( __ICCARM__ ) /*!< IAR compiler */ +#pragma data_alignment=4 +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +#pragma data_alignment=4 +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +#pragma data_alignment=4 +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +#pragma data_alignment=4 +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ + +#endif /* __CC_ARM */ + +/* global transmit and receive descriptors pointers */ +enet_descriptors_struct *dma_current_txdesc; +enet_descriptors_struct *dma_current_rxdesc; + +/* structure pointer of ptp descriptor for normal mode */ +enet_descriptors_struct *dma_current_ptp_txdesc = NULL; +enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; + +/* init structure parameters for ENET initialization */ +static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static uint32_t enet_unknow_err = 0U; + +/* array of register offset for debug information get */ +static const uint16_t enet_reg_tab[] = { +0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x1080, 0x001C, 0x0028, 0x002C, +0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, + +0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1048, 0x104C, +0x1050, 0x1054}; + + +/*! + \brief deinitialize the ENET, and reset structure parameters for ENET initialization + \param[in] none + \param[out] none + \retval none +*/ +void enet_deinit(void) +{ + rcu_periph_reset_enable(RCU_ENETRST); + rcu_periph_reset_disable(RCU_ENETRST); + enet_initpara_reset(); +} + +/*! + \brief configure the parameters which are usually less cared for initialization + note -- this function must be called before enet_init(), otherwise + configuration will be no effect + \param[in] option: different function option, which is related to several parameters, + only one parameter can be selected which is shown as below, refer to enet_option_enum + \arg FORWARD_OPTION: choose to configure the frame forward related parameters + \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters + \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters + \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters + \arg STORE_OPTION: choose to configure the store forward mode related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg VLAN_OPTION: choose to configure vlan related parameters + \arg FLOWCTL_OPTION: choose to configure flow control related parameters + \arg HASHH_OPTION: choose to configure hash high + \arg HASHL_OPTION: choose to configure hash low + \arg FILTER_OPTION: choose to configure frame filter related parameters + \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters + \arg TIMER_OPTION: choose to configure time counter related parameters + \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below + FORWARD_OPTION related parameters: + - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; + - ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ; + - ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE . + DMABUS_OPTION related parameters: + - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; + - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; + DMA_MAXBURST_OPTION related parameters: + - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ + ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ + ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/ + ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/ + ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ; + - ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/ + ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/ + ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/ + ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/ + ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ; + - ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ; + DMA_ARBITRATION_OPTION related parameters: + - ENET_ARBITRATION_RXPRIORTX + - ENET_ARBITRATION_RXTX_1_1/ ENET_ARBITRATION_RXTX_2_1/ + ENET_ARBITRATION_RXTX_3_1/ ENET_ARBITRATION_RXTX_4_1/. + STORE_OPTION related parameters: + - ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ; + - ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ; + - ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/ + ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ; + - ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/ + ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/ + ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/ + ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES . + DMA_OPTION related parameters: + - ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ; + - ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE . + VLAN_OPTION related parameters: + - ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ; + - MAC_VLT_VLTI(regval) . + FLOWCTL_OPTION related parameters: + - MAC_FCTL_PTM(regval) ; + - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; + - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; + - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; + - ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE . + HASHH_OPTION related parameters: + - 0x0~0xFFFF FFFFU + HASHL_OPTION related parameters: + - 0x0~0xFFFF FFFFU + FILTER_OPTION related parameters: + - ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/ + ENET_SRC_FILTER_DISABLE ; + - ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ; + - ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/ + ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ; + - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ + ENET_UNICAST_FILTER_PERFECT ; + - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + HALFDUPLEX_OPTION related parameters: + - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; + - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; + - ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ; + - ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/ + ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ; + - ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE . + TIMER_OPTION related parameters: + - ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ; + - ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ; + INTERFRAMEGAP_OPTION related parameters: + - ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/ + ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ + ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ + ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . + \param[out] none + \retval none +*/ +void enet_initpara_config(enet_option_enum option, uint32_t para) +{ + switch(option){ + case FORWARD_OPTION: + /* choose to configure forward_frame, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; + enet_initpara.forward_frame = para; + break; + case DMABUS_OPTION: + /* choose to configure dmabus_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION; + enet_initpara.dmabus_mode = para; + break; + case DMA_MAXBURST_OPTION: + /* choose to configure dma_maxburst, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION; + enet_initpara.dma_maxburst = para; + break; + case DMA_ARBITRATION_OPTION: + /* choose to configure dma_arbitration, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION; + enet_initpara.dma_arbitration = para; + break; + case STORE_OPTION: + /* choose to configure store_forward_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)STORE_OPTION; + enet_initpara.store_forward_mode = para; + break; + case DMA_OPTION: + /* choose to configure dma_function, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_OPTION; + enet_initpara.dma_function = para; + break; + case VLAN_OPTION: + /* choose to configure vlan_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)VLAN_OPTION; + enet_initpara.vlan_config = para; + break; + case FLOWCTL_OPTION: + /* choose to configure flow_control, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION; + enet_initpara.flow_control = para; + break; + case HASHH_OPTION: + /* choose to configure hashtable_high, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHH_OPTION; + enet_initpara.hashtable_high = para; + break; + case HASHL_OPTION: + /* choose to configure hashtable_low, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHL_OPTION; + enet_initpara.hashtable_low = para; + break; + case FILTER_OPTION: + /* choose to configure framesfilter_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FILTER_OPTION; + enet_initpara.framesfilter_mode = para; + break; + case HALFDUPLEX_OPTION: + /* choose to configure halfduplex_param, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION; + enet_initpara.halfduplex_param = para; + break; + case TIMER_OPTION: + /* choose to configure timer_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; + enet_initpara.timer_config = para; + break; + case INTERFRAMEGAP_OPTION: + /* choose to configure interframegap, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION; + enet_initpara.interframegap = para; + break; + default: + break; + } +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters and the less cared + parameters + \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation + \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex + \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex + \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex + \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex + \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII + \param[in] checksum: IP frame checksum offload function, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function + \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function + \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped + \param[in] recept: frame filter function, only one parameter can be selected + which is shown as below, refer to enet_frmrecept_enum + \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled + \arg ENET_RECEIVEALL: all received frame are forwarded to application + \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames + \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) +{ + uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t media_temp = 0U; + uint32_t timeout = 0U; + uint16_t phy_value = 0U; + ErrStatus phy_state= ERROR, enet_state = ERROR; + + /* PHY interface configuration, configure SMI clock and reset PHY chip */ + if(ERROR == enet_phy_config()){ + _ENET_DELAY_(PHY_RESETDELAY); + if(ERROR == enet_phy_config()){ + return enet_state; + } + } + /* initialize ENET peripheral with generally concerned parameters */ + enet_default_init(); + + /* 1st, configure mediamode */ + media_temp = (uint32_t)mediamode; + /* if is PHY auto negotiation */ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + /* wait for PHY_LINKED_STATUS bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_LINKED_STATUS; + timeout++; + }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* enable auto-negotiation */ + phy_value = PHY_AUTONEGOTIATION; + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_AUTONEGO_COMPLETE; + timeout++; + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* read the result of the auto-negotiation */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + /* configure the duplex mode of MAC following the auto-negotiation result */ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + media_temp = ENET_MODE_FULLDUPLEX; + }else{ + media_temp = ENET_MODE_HALFDUPLEX; + } + /* configure the communication speed of MAC following the auto-negotiation result */ + if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){ + media_temp |= ENET_SPEEDMODE_10M; + }else{ + media_temp |= ENET_SPEEDMODE_100M; + } + }else{ + phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); + phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + /* PHY configuration need some time */ + _ENET_DELAY_(PHY_CONFIGDELAY); + } + /* after configuring the PHY, use mediamode to configure registers */ + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value |= media_temp; + ENET_MAC_CFG = reg_value; + + + /* 2st, configure checksum */ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~ENET_DMA_CTL_DTCERFD; + reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); + ENET_DMA_CTL = reg_value; + } + + /* 3rd, configure recept */ + ENET_MAC_FRMF |= (uint32_t)recept; + + /* 4th, configure different function options */ + /* configure forward_frame related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + reg_temp = enet_initpara.forward_frame; + + reg_value = ENET_MAC_CFG; + temp = reg_temp; + /* configure ENET_MAC_CFG register */ + reg_value &= (~ENET_MAC_CFG_APCD); + temp &= ENET_MAC_CFG_APCD; + reg_value |= temp; + ENET_MAC_CFG = reg_value; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value |= (temp >> 2); + ENET_DMA_CTL = reg_value; + } + + /* configure dmabus_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + temp = enet_initpara.dmabus_mode; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ + |ENET_DMA_BCTL_FPBL); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_maxburst related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + temp = enet_initpara.dma_maxburst; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_arbitration related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + temp = enet_initpara.dma_arbitration; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure store_forward_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + temp = enet_initpara.store_forward_mode; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + } + + /* configure dma_function related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + reg_temp = enet_initpara.dma_function; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + reg_value |= reg_temp; + ENET_DMA_CTL = reg_value; + } + + /* configure vlan_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + reg_temp = enet_initpara.vlan_config; + + reg_value = ENET_MAC_VLT; + /* configure ENET_MAC_VLT register */ + reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); + reg_value |= reg_temp; + ENET_MAC_VLT = reg_value; + } + + /* configure flow_control related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + reg_temp = enet_initpara.flow_control; + + reg_value = ENET_MAC_FCTL; + temp = reg_temp; + /* configure ENET_MAC_FCTL register */ + reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value |= temp; + ENET_MAC_FCTL = reg_value; + + reg_value = ENET_MAC_FCTH; + temp = reg_temp; + /* configure ENET_MAC_FCTH register */ + reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); + reg_value |= (temp >> 8); + ENET_MAC_FCTH = reg_value; + } + + /* configure hashtable_high related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + ENET_MAC_HLH = enet_initpara.hashtable_high; + } + + /* configure hashtable_low related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + ENET_MAC_HLL = enet_initpara.hashtable_low; + } + + /* configure framesfilter_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + reg_temp = enet_initpara.framesfilter_mode; + + reg_value = ENET_MAC_FRMF; + /* configure ENET_MAC_FRMF register */ + reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + reg_value |= reg_temp; + ENET_MAC_FRMF = reg_value; + } + + /* configure halfduplex_param related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + reg_temp = enet_initpara.halfduplex_param; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure timer_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + reg_temp = enet_initpara.timer_config; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure interframegap related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + reg_temp = enet_initpara.interframegap; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~ENET_MAC_CFG_IGBS; + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + enet_state = SUCCESS; + return enet_state; +} + +/*! + \brief reset all core internal registers located in CLK_TX and CLK_RX + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_software_reset(void) +{ + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + uint32_t dma_flag; + + /* reset all core internal registers located in CLK_TX and CLK_RX */ + ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; + + /* wait for reset operation complete */ + do{ + dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); + timeout++; + }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief check receive frame valid and return frame size + \param[in] none + \param[out] none + \retval size of received frame: 0x0 - 0x3FFF +*/ +uint32_t enet_rxframe_size_get(void) +{ + uint32_t size = 0U; + uint32_t status; + + /* get rdes0 information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + + /* if the desciptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + return 0U; + } + + /* if has any error, or the frame uses two or more descriptors */ + if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + /* get the size of the received data including CRC */ + size = GET_RDES0_FRML(status); + /* substract the CRC size */ + size = size - 4U; + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; + } + + /* return packet size */ + return size; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode */ + desc_status = ENET_TDES0_TCHM; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief handle current received frame data to application buffer + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the received frame data + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status); + size = size - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offsetbuffer1_addr) + offset)); + } + + }else{ + /* return ERROR */ + return ERROR; + } + } + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief handle application buffer data to transmit it + \param[in] buffer: pointer to the frame data to be transmitted, + note -- if the input is NULL, user should handle the data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) +{ + uint32_t offset = 0U; + uint32_t dma_tbu_flag, dma_tu_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief configure the transmit IP frame checksum offload calculation and insertion + \param[in] desc: the descriptor pointer which users want to configure + \param[in] checksum: IP frame checksum configuration + only one parameter can be selected which is shown as below + \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled + \arg ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled + \arg ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header + \arg ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated + \param[out] none + \retval none +*/ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum) +{ + desc->status &= ~ENET_TDES0_CM; + desc->status |= checksum; +} + +/*! + \brief ENET Tx and Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_enable(void) +{ + enet_tx_enable(); + enet_rx_enable(); +} + +/*! + \brief ENET Tx and Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_disable(void) +{ + enet_tx_disable(); + enet_rx_disable(); +} + +/*! + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: set MAC address 0 filter + \arg ENET_MAC_ADDRESS1: set MAC address 1 filter + \arg ENET_MAC_ADDRESS2: set MAC address 2 filter + \arg ENET_MAC_ADDRESS3: set MAC address 3 filter + \param[in] paddr: the buffer pointer which stores the MAC address + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[out] none + \retval none +*/ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); + REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr); +} + +/*! + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: get MAC address 0 filter + \arg ENET_MAC_ADDRESS1: get MAC address 1 filter + \arg ENET_MAC_ADDRESS2: get MAC address 2 filter + \arg ENET_MAC_ADDRESS3: get MAC address 3 filter + \param[out] paddr: the buffer pointer which is stored the MAC address + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \retval none +*/ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); + paddr[1] = ENET_GET_MACADDR(mac_addr, 1U); + paddr[2] = ENET_GET_MACADDR(mac_addr, 2U); + paddr[3] = ENET_GET_MACADDR(mac_addr, 3U); + paddr[4] = ENET_GET_MACADDR(mac_addr, 4U); + paddr[5] = ENET_GET_MACADDR(mac_addr, 5U); +} + +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + +/*! + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; +} + +/*! + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; +} + +/*! + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; +} + +/*! + \brief ENET Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE; + ENET_MAC_CFG &= ~ENET_MAC_CFG_REN; +} + +/*! + \brief put registers value into the application buffer + \param[in] type: register type which will be get, refer to enet_registers_type_enum, + only one parameter can be selected which is shown as below + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT + \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL + \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR + \param[in] num: the number of registers that the user want to get + \param[out] preg: the application buffer pointer for storing the register value + \retval none +*/ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) +{ + uint32_t offset = 0U, max = 0U, limit = 0U; + + offset = (uint32_t)type; + max = (uint32_t)type + num; + limit = sizeof(enet_reg_tab)/sizeof(uint16_t); + + /* prevent element in this array is out of range */ + if(max > limit){ + max = limit; + } + + for(; offset < max; offset++){ + /* get value of the corresponding register */ + *preg = REG32((ENET) + enet_reg_tab[offset]); + preg++; + } +} + +/*! + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable + \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_enable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: disable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_disable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter + \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter + \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter + \param[in] addr_mask: select which MAC address bytes will be mask, + one or more parameters can be selected which are shown as below + \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits + \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits + \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits + \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits + \param[in] filter_type: select which MAC address filter type will be selected, + only one parameter can be selected which is shown as below + \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame + \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame + \param[out] none + \retval none +*/ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) +{ + uint32_t reg; + + /* get the address filter register value which is to be configured */ + reg = REG32(ENET_ADDRH_BASE + mac_addr); + + /* clear and configure the address filter register */ + reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF); + reg |= (addr_mask | filter_type); + REG32(ENET_ADDRH_BASE + mac_addr) = reg; +} + +/*! + \brief PHY interface configuration (configure SMI clock and reset PHY chip) + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_config(void) +{ + uint32_t ahbclk; + uint32_t reg; + uint16_t phy_value; + ErrStatus enet_state = ERROR; + + /* clear the previous MDC clock */ + reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + /* get the HCLK frequency */ + ahbclk = rcu_clock_freq_get(CK_AHB); + + /* configure MDC clock according to HCLK frequency range */ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + reg |= ENET_MDC_HCLK_DIV16; + }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + reg |= ENET_MDC_HCLK_DIV26; + }else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)){ + reg |= ENET_MDC_HCLK_DIV42; + }else if((ENET_RANGE(ahbclk, 100000000U, 120000000U))||(120000000U == ahbclk)){ + reg |= ENET_MDC_HCLK_DIV62; + }else{ + return enet_state; + } + ENET_MAC_PHY_CTL = reg; + + /* reset PHY */ + phy_value = PHY_RESET; + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + /* PHY reset need some time */ + _ENET_DELAY_(ENET_DELAY_TO); + + /* check whether PHY reset is complete */ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + + /* PHY reset complete */ + if(RESET == (phy_value & PHY_RESET)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief write to / read from a PHY register + \param[in] direction: only one parameter can be selected which is shown as below + \arg ENET_PHY_WRITE: write data to phy register + \arg ENET_PHY_READ: read data from phy register + \param[in] phy_address: 0x0 - 0x1F + \param[in] phy_reg: 0x0 - 0x1F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue) +{ + uint32_t reg, phy_flag; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* configure ENET_MAC_PHY_CTL with write/read operation */ + reg = ENET_MAC_PHY_CTL; + reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + + /* if do the write operation, write value to the register */ + if(ENET_PHY_WRITE == direction){ + ENET_MAC_PHY_DATA = *pvalue; + } + + /* do PHY write/read operation, and wait the operation complete */ + ENET_MAC_PHY_CTL = reg; + do{ + phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); + timeout++; + } + while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + enet_state = SUCCESS; + } + + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction){ + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + } + + return enet_state; +} + +/*! + \brief enable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_enable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* enable the PHY loopback mode */ + temp_phy |= PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief disable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_disable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* disable the PHY loopback mode */ + temp_phy &= (uint16_t)~PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief enable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_enable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG |= mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL |= (mask >> 2); +} + +/*! + \brief disable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the automatic zero-quanta generation function + \arg ENET_FORWARD_ERRFRAMES: decoding function for the received pause frame and process it + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_forward_feature_disable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG &= ~mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL &= ~(mask >> 2); +} + +/*! + \brief enable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_enable(uint32_t feature) +{ + ENET_MAC_FRMF |= feature; +} + +/*! + \brief disable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_disable(uint32_t feature) +{ + ENET_MAC_FRMF &= ~feature; +} + +/*! + \brief generate the pause frame, ENET will send pause frame after enable transmit flow control + this function only use in full-dulex mode + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state =ERROR; + uint32_t temp = 0U; + + /* in full-duplex mode, must make sure this bit is 0 before writing register */ + temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; + if(RESET == temp){ + ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; + enet_state = SUCCESS; + } + return enet_state; +} + +/*! + \brief configure the pause frame detect type + \param[in] detect: pause frame detect type, + only one parameter can be selected which is shown as below + \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also + use the MAC0 address to detecting pause frame + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + in IEEE802.3 can be detected + \param[out] none + \retval none +*/ +void enet_pauseframe_detect_config(uint32_t detect) +{ + ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT; + ENET_MAC_FCTL |= detect; +} + +/*! + \brief configure the pause frame parameters + \param[in] pausetime: pause time in transmit pause control frame + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, + this value must make sure to be less than configured pause time, only one parameter can be + selected which is shown as below + \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times + \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times + \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times + \arg ENET_PAUSETIME_MINUS256: pause time minus 256 slot times + \param[out] none + \retval none +*/ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) +{ + ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS); + ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold); +} + +/*! + \brief configure the threshold of the flow control(deactive and active threshold) + \param[in] deactive: the threshold of the deactive flow control, this value + should always be less than active flow control value, only one + parameter can be selected which is shown as below + \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[in] active: the threshold of the active flow control, only one parameter + can be selected which is shown as below + \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[out] none + \retval none +*/ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) +{ + ENET_MAC_FCTH = ((deactive | active) >> 8); +} + +/*! + \brief enable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_enable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL |= feature; +} + +/*! + \brief disable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_disable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL &= ~feature; +} + +/*! + \brief get the dma transmit/receive process state + \param[in] direction: choose the direction of dma process which users want to check, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: dma transmit process + \arg ENET_DMA_RX: dma receive process + \param[out] none + \retval state of dma process, the value range shows below: + ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING, + ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING, + ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING, + ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING +*/ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) +{ + uint32_t reval; + reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction); + return reval; +} + +/*! + \brief poll the DMA transmission/reception enable by writing any value to the + ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception + \param[in] direction: choose the direction of DMA process which users want to resume, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA transmit process + \arg ENET_DMA_RX: DMA receive process + \param[out] none + \retval none +*/ +void enet_dmaprocess_resume(enet_dmadirection_enum direction) +{ + if(ENET_DMA_TX == direction){ + ENET_DMA_TPEN = 0U; + }else{ + ENET_DMA_RPEN = 0U; + } +} + +/*! + \brief check and recover the Rx process + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxprocess_check_recovery(void) +{ + uint32_t status; + + /* get DAV information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + status &= ENET_RDES0_DAV; + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with + receive descriptor address pointer updated by RxDMA controller */ + if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && + (ENET_RDES0_DAV == status)){ + dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + } +} + +/*! + \brief flush the ENET transmit FIFO, and wait until the flush operation completes + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_txfifo_flush(void) +{ + uint32_t flush_state; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* set the FTF bit for flushing transmit FIFO */ + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + /* wait until the flush operation completes */ + do{ + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + timeout++; + }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(RESET == flush_state){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + only one parameter can be selected which is shown as below + \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table + \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by + the RxDMA controller + \arg ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller + \arg ENET_TX_DESC_TABLE: the start address of the transmit descriptor table + \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by + the TxDMA controller + \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller + \param[out] none + \retval address value +*/ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) +{ + uint32_t reval = 0U; + + reval = REG32((ENET) +(uint32_t)addr_get); + return reval; +} + +/*! + \brief get the Tx or Rx descriptor information + \param[in] desc: the descriptor pointer which users want to get information + \param[in] info_get: the descriptor information type which is selected, + only one parameter can be selected which is shown as below + \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size + \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size + \arg RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer + \arg TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted + \arg RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame + \arg TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame + \param[out] none + \retval descriptor information, if value is 0xFFFFFFFFU, means the false input parameter +*/ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch(info_get){ + case RXDESC_BUFFER_1_SIZE: + reval = GET_RDES1_RB1S(desc->control_buffer_size); + break; + case RXDESC_BUFFER_2_SIZE: + reval = GET_RDES1_RB2S(desc->control_buffer_size); + break; + case RXDESC_FRAME_LENGTH: + reval = GET_RDES0_FRML(desc->status); + if(reval > 4U){ + reval = reval - 4U; + }else{ + reval = 0U; + } + break; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_COLLISION_COUNT: + reval = GET_TDES0_COCNT(desc->status); + break; + default: + break; + } + return reval; +} + +/*! + \brief get the number of missed frames during receiving + \param[in] none + \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO + \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller + \retval none +*/ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) +{ + uint32_t temp_counter = 0U; + + temp_counter = ENET_DMA_MFBOCNT; + *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); + *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); +} + +/*! + \brief get the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_UFE: underflow error + \arg ENET_TDES0_EXD: excessive deferral + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_ECO: excessive collision + \arg ENET_TDES0_LCO: late collision + \arg ENET_TDES0_NCA: no carrier + \arg ENET_TDES0_LCA: loss of carrier + \arg ENET_TDES0_IPPE: IP payload error + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_JT: jabber timeout + \arg ENET_TDES0_ES: error summary + \arg ENET_TDES0_IPHE: IP header error + \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + + \arg ENET_RDES0_PCERR: payload checksum error + \arg ENET_RDES0_CERR: CRC error + \arg ENET_RDES0_DBERR: dribble bit error + \arg ENET_RDES0_RERR: receive error + \arg ENET_RDES0_RWDT: receive watchdog timeout + \arg ENET_RDES0_FRMT: frame type + \arg ENET_RDES0_LCO: late collision + \arg ENET_RDES0_IPHERR: IP frame header error + \arg ENET_RDES0_LDES: last descriptor + \arg ENET_RDES0_FDES: first descriptor + \arg ENET_RDES0_VTAG: VLAN tag + \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_LERR: length error + \arg ENET_RDES0_SAFF: SA filter fail + \arg ENET_RDES0_DERR: descriptor error + \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_DAFF: destination address filter fail + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + FlagStatus enet_flag = RESET; + + if ((uint32_t)RESET != (desc->status & desc_flag)){ + enet_flag = SET; + } + + return enet_flag; +} + +/*! + \brief set the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to set flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status |= desc_flag; +} + +/*! + \brief clear the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to clear flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status &= ~desc_flag; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size &= ~ENET_RDES1_DINTC; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will not set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size |= ENET_RDES1_DINTC; +} + +/*! + \brief drop current receive frame + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxframe_drop(void) +{ + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } + + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + } + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc++; + } + } + } +} + +/*! + \brief enable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_enable(uint32_t feature) +{ + ENET_DMA_CTL |= feature; +} + +/*! + \brief disable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_disable(uint32_t feature) +{ + ENET_DMA_CTL &= ~feature; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive ring mode and set buffer1 size */ + desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] timestamp: pointer to the table which stores the timestamp high and low + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); + } + + }else{ + return ERROR; + } + } + /* copy timestamp value from Rx descriptor to application array */ + timestamp[0] = dma_current_rxdesc->buffer1_addr; + timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with RxDMA descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_rxdesc ++; + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0U, timeout = 0U; + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->buffer1_addr; + timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_txdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with TxDMA descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; + } + } + return SUCCESS; +} + +/*! + \brief wakeup frame filter register pointer reset + \param[in] none + \param[out] none + \retval none +*/ +void enet_wum_filter_register_pointer_reset(void) +{ + ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR; +} + +/*! + \brief set the remote wakeup frame registers + \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) + \param[out] none + \retval none +*/ +void enet_wum_filter_config(uint32_t pdata[]) +{ + uint32_t num = 0U; + + /* configure ENET_MAC_RWFF register */ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + ENET_MAC_RWFF = pdata[num]; + } +} + +/*! + \brief enable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_POWER_DOWN: power down mode + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_enable(uint32_t feature) +{ + ENET_MAC_WUM |= feature; +} + +/*! + \brief disable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_disable(uint32_t feature) +{ + ENET_MAC_WUM &= (~feature); +} + +/*! + \brief reset the MAC statistics counters + \param[in] none + \param[out] none + \retval none +*/ +void enet_msc_counters_reset(void) +{ + /* reset all counters */ + ENET_MSC_CTL |= ENET_MSC_CTL_CTR; +} + +/*! + \brief enable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_enable(uint32_t feature) +{ + ENET_MSC_CTL |= feature; +} + +/*! + \brief disable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_disable(uint32_t feature) +{ + ENET_MSC_CTL &= (~feature); +} + +/*! + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter + \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter + \arg ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter + \arg ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter + \arg ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter + \arg ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter + \param[out] none + \retval the MSC counter value +*/ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) +{ + uint32_t reval; + + reval = REG32((ENET + (uint32_t)counter)); + + return reval; +} + +/*! + \brief change subsecond to nanosecond + \param[in] subsecond: subsecond value + \param[out] none + \retval the nanosecond value +*/ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) +{ + uint64_t val = subsecond * 1000000000Ull; + val >>= 31; + return (uint32_t)val; +} + +/*! + \brief change nanosecond to subsecond + \param[in] nanosecond: nanosecond value + \param[out] none + \retval the subsecond value +*/ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond) +{ + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return (uint32_t)val; +} + +/*! + \brief enable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_enable(uint32_t feature) +{ + ENET_PTP_TSCTL |= feature; +} + +/*! + \brief disable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_disable(uint32_t feature) +{ + ENET_PTP_TSCTL &= ~feature; +} + +/*! + \brief configure the PTP timestamp function + \param[in] func: only one parameter can be selected which is shown as below + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \arg ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating + \arg ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ + +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) +{ + uint32_t temp_config = 0U, temp_state = 0U; + uint32_t timeout = 0U; + ErrStatus enet_state = SUCCESS; + + switch(func){ + case ENET_PTP_ADDEND_UPDATE: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; + } + break; + case ENET_PTP_SYSTIME_UPDATE: + /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ + do{ + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; + } + break; + case ENET_PTP_SYSTIME_INIT: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; + } + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; + } + + return enet_state; +} + +/*! + \brief configure system time subsecond increment value + \param[in] subsecond: the value will be added to the subsecond value of system time, + this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_ptp_subsecond_increment_config(uint32_t subsecond) +{ + ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond); +} + +/*! + \brief adjusting the clock frequency only in fine update mode + \param[in] add: the value will be added to the accumulator register to achieve time synchronization + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_addend_config(uint32_t add) +{ + ENET_PTP_TSADDEND = add; +} + +/*! + \brief initialize or add/subtract to second of the system time + \param[in] sign: timestamp update positive or negative sign, + only one parameter can be selected which is shown as below + \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time + \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time + \param[in] second: initializing or adding/subtracting to second of the system time + \param[in] subsecond: the current subsecond of the system time + with 0.46 ns accuracy if required accuracy is 20 ns + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) +{ + ENET_PTP_TSUH = second; + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); +} + +/*! + \brief configure the expected target time + \param[in] second: the expected target second time + \param[in] nanosecond: the expected target nanosecond time (signed) + \param[out] none + \retval none +*/ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) +{ + ENET_PTP_ETH = second; + ENET_PTP_ETL = nanosecond; +} + +/*! + \brief get the current system time + \param[in] none + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \retval none +*/ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) +{ + uint32_t temp_sec = 0U, temp_subs = 0U; + + /* get the value of sysytem time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; + temp_subs = (uint32_t)ENET_PTP_TSL; + + /* get sysytem time and construct the enet_ptp_systime_struct structure */ + systime_struct->second = temp_sec; + systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); + systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); + systime_struct->sign = GET_PTP_TSL_STS(temp_subs); +} + +/*! + \brief configure and start PTP timestamp counter + \param[in] updatemethod: method for updating + \arg ENET_PTP_FINEMODE: fine correction method + \arg ENET_PTP_COARSEMODE: coarse correction method + \param[in] init_sec: second value for initializing system time + \param[in] init_subsec: subsecond value for initializing system time + \param[in] carry_cfg: the value to be added to the accumulator register (in fine method is used) + \param[in] accuracy_cfg: the value to be added to the subsecond value of system time + \param[out] none + \retval none +*/ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg) +{ + /* mask the timestamp trigger interrupt */ + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + + /* enable timestamp */ + enet_ptp_feature_enable(ENET_RXTX_TIMESTAMP); + + /* configure system time subsecond increment based on the PTP clock frequency */ + enet_ptp_subsecond_increment_config(accuracy_cfg); + + if(ENET_PTP_FINEMODE == updatemethod){ + /* fine correction method: configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + /* wait until update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + } + } + + /* choose the fine correction method */ + enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); +} + +/*! + \brief adjust frequency in fine method by configure addend register + \param[in] carry_cfg: the value to be added to the accumulator register + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) +{ + /* re-configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config((uint32_t)carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief update system time in coarse method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct) +{ + uint32_t subsecond_val; + uint32_t carry_cfg; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* save the carry_cfg value */ + carry_cfg = ENET_PTP_TSADDEND_TMSA; + + /* update the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + + /* wait until the update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + } + + /* write back the carry_cfg value, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief set system time in fine method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +{ + uint32_t subsecond_val; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + + /* wait until the system time initialzation finished */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + } +} + +/*! + \brief get the ptp flag status + \param[in] flag: ptp flag status to be checked + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_ptp_flag_get(uint32_t flag) +{ + FlagStatus bitstatus = RESET; + + if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + bitstatus = SET; + } + + return bitstatus; +} + +/*! + \brief reset the ENET initpara struct, call it before using enet_initpara_config() + \param[in] none + \param[out] none + \retval none +*/ +void enet_initpara_reset(void) +{ + enet_initpara.option_enable = 0U; + enet_initpara.forward_frame = 0U; + enet_initpara.dmabus_mode = 0U; + enet_initpara.dma_maxburst = 0U; + enet_initpara.dma_arbitration = 0U; + enet_initpara.store_forward_mode = 0U; + enet_initpara.dma_function = 0U; + enet_initpara.vlan_config = 0U; + enet_initpara.flow_control = 0U; + enet_initpara.hashtable_high = 0U; + enet_initpara.hashtable_low = 0U; + enet_initpara.framesfilter_mode = 0U; + enet_initpara.halfduplex_param = 0U; + enet_initpara.timer_config = 0U; + enet_initpara.interframegap = 0U; +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \param[in] none + \param[out] none + \retval none +*/ +static void enet_default_init(void) +{ + uint32_t reg_value = 0U; + + /* MAC */ + /* configure ENET_MAC_CFG register */ + reg_value = ENET_MAC_CFG; + reg_value &= MAC_CFG_MASK; + reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ + | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; + ENET_MAC_CFG = reg_value; + + /* configure ENET_MAC_FRMF register */ + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ + |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ + |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ + |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + + /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ + ENET_MAC_HLH = 0x0U; + + ENET_MAC_HLL = 0x0U; + + /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ + reg_value = ENET_MAC_FCTL; + reg_value &= MAC_FCTL_MASK; + reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ + |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ + |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + + ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES; + + /* configure ENET_MAC_VLT register */ + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); + + /* DMA */ + /* configure ENET_DMA_CTL register */ + reg_value = ENET_DMA_CTL; + reg_value &= DMA_CTL_MASK; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ + |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ + |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ + |ENET_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \ + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; + + /* configure ENET_DMA_BCTL register */ + reg_value = ENET_DMA_BCTL; + reg_value &= DMA_BCTL_MASK; + reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ + |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ + |ENET_FIXED_BURST_ENABLE; + ENET_DMA_BCTL = reg_value; +} + +#ifndef USE_DELAY +/*! + \brief insert a delay time + \param[in] ncount: specifies the delay time length + \param[out] none + \param[out] none +*/ +static void enet_delay(uint32_t ncount) +{ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--){ + } +} +#endif /* USE_DELAY */ + +#endif /* GD32F20X_CL */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c new file mode 100644 index 0000000000..cc2e62728c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c @@ -0,0 +1,1178 @@ +/*! + \file gd32f20x_exmc.c + \brief EXMC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_exmc.h" + +/* EXMC bank0 register reset value */ +#define BANK0_SNCTL_RESET ((uint32_t)0x000030DAU) +#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) + +/* EXMC bank1/2 register reset mask*/ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000008U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000042U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFFFFFFFFU) + +/* EXMC bank3 register reset mask*/ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000008U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000043U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFFFFFFFFU) + +/* EXMC SDRAM device register reset mask */ +#define SDRAM_DEVICE_SDCTL_RESET ((uint32_t)0x000002D0U) +#define SDRAM_DEVICE_SDTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define SDRAM_DEVICE_SDCMD_RESET ((uint32_t)0x00000000U) +#define SDRAM_DEVICE_SDARI_RESET ((uint32_t)0x00000000U) +#define SDRAM_DEVICE_SDSTAT_RESET ((uint32_t)0x00000000U) +#define SDRAM_DEVICE_SDRSCTL_RESET ((uint32_t)0x00000000U) + +/* EXMC bank0 SQPI-PSRAM register reset mask */ +#define BANK0_SQPI_SINIT_RESET ((uint32_t)0x18010000U) +#define BANK0_SQPI_SRCMD_RESET ((uint32_t)0x00000000U) +#define BANK0_SQPI_SWCMD_RESET ((uint32_t)0x00000000U) +#define BANK0_SQPI_SIDL_RESET ((uint32_t)0x00000000U) +#define BANK0_SQPI_SIDH_RESET ((uint32_t)0x00000000U) + +/* EXMC register bit offset */ +#define SNCTL_NRMUX_OFFSET ((uint32_t)1U) +#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U) +#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U) +#define SNCTL_WREN_OFFSET ((uint32_t)12U) +#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U) +#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U) +#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U) + +#define SNTCFG_AHLD_OFFSET ((uint32_t)4U) +#define SNTCFG_DSET_OFFSET ((uint32_t)8U) +#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U) + +#define NPCTL_NDWTEN_OFFSET ((uint32_t)1U) +#define NPCTL_ECCEN_OFFSET ((uint32_t)6U) + +#define NPCTCFG_COMWAIT_OFFSET ((uint32_t)8U) +#define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) +#define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) + +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) + +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) + +#define SDCTL_WPEN_OFFSET ((uint32_t)9U) +#define SDCTL_BRSTRD_OFFSET ((uint32_t)12U) + +#define SDTCFG_XSRD_OFFSET ((uint32_t)4U) +#define SDTCFG_RASD_OFFSET ((uint32_t)8U) +#define SDTCFG_ARFD_OFFSET ((uint32_t)12U) +#define SDTCFG_WRD_OFFSET ((uint32_t)16U) +#define SDTCFG_RPD_OFFSET ((uint32_t)20U) +#define SDTCFG_RCD_OFFSET ((uint32_t)24U) + +#define SDCMD_NARF_OFFSET ((uint32_t)5U) +#define SDCMD_MRC_OFFSET ((uint32_t)9U) + +#define SDARI_ARINTV_OFFSET ((uint32_t)1U) + +#define SDRSCTL_SSCR_OFFSET ((uint32_t)1U) +#define SDRSCTL_SDSC_OFFSET ((uint32_t)4U) + +#define SDSTAT_STA0_OFFSET ((uint32_t)1U) +#define SDSTAT_STA1_OFFSET ((uint32_t)3U) + +#define SRCMD_RWAITCYCLE_OFFSET ((uint32_t)16U) +#define SWCMD_WWAITCYCLE_OFFSET ((uint32_t)16U) + +#define INTEN_INTS_OFFSET ((uint32_t)3U) + +/*! + \brief deinitialize EXMC NOR/SRAM region + \param[in] exmc_norsram_region: select the region of bank0 + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_deinit(uint32_t exmc_norsram_region) +{ + /* reset the registers */ + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_RESET; + EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET; + EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET; +} + +/*! + \brief initialize the struct exmc_norsram_parameter_struct + \param[in] none + \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + /* configure the structure with default value */ + exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; + exmc_norsram_init_struct->address_data_mux = ENABLE; + exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; + exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B; + exmc_norsram_init_struct->burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW; + exmc_norsram_init_struct->wrap_burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE; + exmc_norsram_init_struct->memory_write = ENABLE; + exmc_norsram_init_struct->nwait_signal = ENABLE; + exmc_norsram_init_struct->extended_mode = DISABLE; + exmc_norsram_init_struct->asyn_wait = DISABLE; + exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; + + /* read/write timing configure */ + exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK; + exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; + exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; + + /* write timing configure, when extended mode is used */ + exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; +} + +/*! + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 + write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE or EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW or EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B or EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM / EXMC_MEMORY_TYPE_PSRAM / EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D + syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 + syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x01U~0x10U + asyn_data_setuptime: 0x02U~0x100U + asyn_address_holdtime: 0x02U~0x10U + asyn_address_setuptime: 0x01U~0x10U + write_timing: struct exmc_norsram_timing_parameter_struct set the time + asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D + syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 + syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x01U~0x10U + asyn_data_setuptime: 0x02U~0x100U + asyn_address_holdtime: 0x02U~0x10U + asyn_address_setuptime: 0x01U~0x10U + \param[out] none + \retval none +*/ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | + EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | + EXMC_SNCTL_NRMUX )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U) & EXMC_SNTCFG_ASET) | + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET) & EXMC_SNTCFG_AHLD) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNTCFG_DSET) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U) << SNTCFG_BUSLAT_OFFSET) & EXMC_SNTCFG_BUSLAT) | + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; + } + + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)(((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET) | + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD)| + (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNWTCFG_WDSET) | + exmc_norsram_init_struct->write_timing->asyn_access_mode); + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } + + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; +} + +/*! + \brief enable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_enable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief disable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM Bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_disable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief deinitialize EXMC NAND bank + \param[in] exmc_nand_bank: select the bank of NAND + \arg EXMC_BANKx_NAND(x=1..2) + \param[out] none + \retval none +*/ +void exmc_nand_deinit(uint32_t exmc_nand_bank) +{ + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET; + EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET; + EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET; + EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET; +} + +/*! + \brief initialize the struct exmc_nand_init_struct + \param[in] none + \param[out] the initialized struct exmc_nand_init_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default value */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief initialize EXMC NAND bank + \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter + nand_bank: EXMC_BANK1_NAND or EXMC_BANK2_NAND + ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + ecc_logic: ENABLE or DISABLE + databus_width: EXMC_NAND_DATABUS_WIDTH_8B or EXMC_NAND_DATABUS_WIDTH_16B + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + \param[out] none + \retval none +*/ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; + EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; + EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; +} + +/*! + \brief enable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_enable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_disable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_ECCEN; + } +} + +/*! + \brief get the EXMC ECC value + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank) +{ + return(EXMC_NECC(exmc_nand_bank)); +} + +/*! + \brief deinitialize EXMC PC card bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_deinit(void) +{ + /* EXMC_BANK3_PCCARD */ + EXMC_NPCTL3 = BANK3_NPCTL_RESET; + EXMC_NPINTEN3 = BANK3_NPINTEN_RESET; + EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET; + EXMC_NPATCFG3 = BANK3_NPATCFG_RESET; + EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; +} + +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x00U~0xFFU + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD ) | + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + +/*! + \brief initialize the struct exmc_pccard_parameter_struct + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the structure with default value */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief enable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_enable(void) +{ + EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_disable(void) +{ + EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief deinitialize EXMC SDRAM device + \param[in] exmc_sdram_device: + \param[out] none + \retval none +*/ +void exmc_sdram_deinit(uint32_t exmc_sdram_device) +{ + /* reset SDRAM registers */ + EXMC_SDCTL(exmc_sdram_device) = SDRAM_DEVICE_SDCTL_RESET; + EXMC_SDTCFG(exmc_sdram_device) = SDRAM_DEVICE_SDTCFG_RESET; + EXMC_SDCMD = SDRAM_DEVICE_SDCMD_RESET; + EXMC_SDARI = SDRAM_DEVICE_SDARI_RESET; + EXMC_SDRSCTL = SDRAM_DEVICE_SDRSCTL_RESET; +} + +/*! + \brief initialize EXMC SDRAM device + \param[in] exmc_sdram_parameter_struct: configure the EXMC SDRAM parameter + sdram_device: EXMC_SDRAM_DEVICE0 or EXMC_SDRAM_DEVICE1 + pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK, x=0..2 + brust_read_switch: ENABLE or DISABLE + sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK + write_protection: ENABLE or DISABLE + cas_latency: EXMC_CAS_LATENCY_x_SDCLK, x=1..3 + internal_bank_number: EXMC_SDRAM_2_INTER_BANK or EXMC_SDRAM_4_INTER_BANK + data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B + row_address_width: EXMC_SDRAM_ROW_ADDRESS_x, x=11..13 + column_address_width: EXMC_SDRAM_COW_ADDRESS_x, x=8..11 + timing: exmc_sdram_timing_parameter_struct set the time + row_to_column_delay: 1U~16U + row_precharge_delay: 1U~16U + write_recovery_delay: 1U~16U + auto_refresh_delay: 1U~16U + row_address_select_delay: 1U~16U + exit_selfrefresh_delay: 1U~16U + load_mode_register_delay: 1U~16U + \param[out] none + \retval none +*/ +void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +{ + uint32_t sdctl0, sdctl1, sdtcfg0, sdtcfg1; + + /* configuration EXMC_SDCTL0 or EXMC_SDCTL1 */ + if(EXMC_SDRAM_DEVICE0 == exmc_sdram_init_struct->sdram_device){ + /* configuration EXMC_SDCTL0 */ + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = (uint32_t)exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET)| + exmc_sdram_init_struct->sdclock_config | + (exmc_sdram_init_struct->brust_read_switch << SDCTL_BRSTRD_OFFSET)| + exmc_sdram_init_struct->pipeline_read_delay; + + /* configuration EXMC_SDTCFG0 */ + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); + }else{ + /* configuration EXMC_SDCTL0 and EXMC_SDCTL1 */ + /* some bits in the EXMC_SDCTL1 register are reserved */ + sdctl0 = EXMC_SDCTL(EXMC_SDRAM_DEVICE0) & (~( EXMC_SDCTL_PIPED | EXMC_SDCTL_BRSTRD | EXMC_SDCTL_SDCLK )); + + sdctl0 |= (uint32_t)exmc_sdram_init_struct->sdclock_config | + exmc_sdram_init_struct->brust_read_switch | + exmc_sdram_init_struct->pipeline_read_delay; + + sdctl1 = (uint32_t)exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + exmc_sdram_init_struct->write_protection ; + + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = sdctl0; + EXMC_SDCTL(EXMC_SDRAM_DEVICE1) = sdctl1; + + /* configuration EXMC_SDTCFG0 and EXMC_SDTCFG1 */ + /* some bits in the EXMC_SDTCFG1 register are reserved */ + sdtcfg0 = EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) & (~(EXMC_SDTCFG_RPD | EXMC_SDTCFG_WRD | EXMC_SDTCFG_ARFD)); + + sdtcfg0 |= (uint32_t)(((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET); + + sdtcfg1 = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); + + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = sdtcfg0; + EXMC_SDTCFG(EXMC_SDRAM_DEVICE1) = sdtcfg1; + } +} + +/*! + \brief initialize the struct exmc_sdram_parameter_struct + \param[in] none + \param[out] the initialized struct exmc_sdram_parameter_struct pointer + \retval none +*/ +void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +{ + /* configure the structure with default value */ + exmc_sdram_init_struct->sdram_device = EXMC_SDRAM_DEVICE0; + exmc_sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_8; + exmc_sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_11; + exmc_sdram_init_struct->data_width = EXMC_SDRAM_DATABUS_WIDTH_16B; + exmc_sdram_init_struct->internal_bank_number = EXMC_SDRAM_4_INTER_BANK; + exmc_sdram_init_struct->cas_latency = EXMC_CAS_LATENCY_1_SDCLK; + exmc_sdram_init_struct->write_protection = ENABLE; + exmc_sdram_init_struct->sdclock_config = EXMC_SDCLK_DISABLE; + exmc_sdram_init_struct->brust_read_switch = DISABLE; + exmc_sdram_init_struct->pipeline_read_delay = EXMC_PIPELINE_DELAY_0_HCLK; + + exmc_sdram_init_struct->timing->load_mode_register_delay = 16U; + exmc_sdram_init_struct->timing->exit_selfrefresh_delay = 16U; + exmc_sdram_init_struct->timing->row_address_select_delay = 16U; + exmc_sdram_init_struct->timing->auto_refresh_delay = 16U; + exmc_sdram_init_struct->timing->write_recovery_delay = 16U; + exmc_sdram_init_struct->timing->row_precharge_delay = 16U; + exmc_sdram_init_struct->timing->row_to_column_delay = 16U; +} + +/*! + \brief configure the SDRAM memory command + \param[in] exmc_sdram_command_init_struct: initialize EXMC SDRAM command + mode_register_content: + auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 + bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT + command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY + \param[out] none + \retval none +*/ +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct) +{ + /* configure command register */ + EXMC_SDCMD = (uint32_t)((exmc_sdram_command_init_struct->command) | + (exmc_sdram_command_init_struct->bank_select) | + ((exmc_sdram_command_init_struct->auto_refresh_number)) | + ((exmc_sdram_command_init_struct->mode_register_content)<> SDSTAT_STA0_OFFSET); + }else{ + sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA1) >> SDSTAT_STA1_OFFSET); + } + + return sdstat; +} + +/*! + \brief configure the delayed sample clock of read data + \param[in] delay_cell: SDRAM the delayed sample clock of read data + \arg EXMC_SDRAM_x_DELAY_CELL(x=0..15) + \param[in] extra_hclk: sample cycle of read data + \arg EXMC_SDRAM_READSAMPLE_x_EXTRAHCLK(x=0,1) + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk) +{ + uint32_t sdrsctl = 0U; + + sdrsctl = EXMC_SDRSCTL & (~(EXMC_SDRSCTL_SDSC | EXMC_SDRSCTL_SSCR)); + sdrsctl |= (uint32_t)(delay_cell & EXMC_SDRSCTL_SDSC) | + ((extra_hclk << SDRSCTL_SSCR_OFFSET) & EXMC_SDRSCTL_SSCR); + EXMC_SDRSCTL = sdrsctl; +} + +/*! + \brief enable read sample + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_enable(void) +{ + EXMC_SDRSCTL |= EXMC_SDRSCTL_RSEN; +} + +/*! + \brief disable read sample + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_disable(void) +{ + EXMC_SDRSCTL &= (uint32_t)(~EXMC_SDRSCTL_RSEN); +} + + +/*! + \brief deinitialize exmc SQPIPSRAM + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sqpipsram_deinit(void) +{ + /* reset the registers */ + EXMC_SINIT = BANK0_SQPI_SINIT_RESET; + EXMC_SRCMD = BANK0_SQPI_SRCMD_RESET; + EXMC_SWCMD = BANK0_SQPI_SWCMD_RESET; + EXMC_SIDL = BANK0_SQPI_SIDL_RESET; + EXMC_SIDH = BANK0_SQPI_SIDH_RESET; +} + +/*! + \brief initialize EXMC SQPIPSRAM + \param[in] exmc_sqpipsram_parameter_struct: configure the EXMC SQPIPSRAM parameter + sample_polarity: EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE, EXMC_SQPIPSRAM_SAMPLE_FALLING_EDGE + id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 + address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 + command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 + \param[out] none + \retval none +*/ +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +{ + /* initialize SQPI controller */ + EXMC_SINIT = (uint32_t)exmc_sqpipsram_init_struct->sample_polarity | + exmc_sqpipsram_init_struct->id_length | + exmc_sqpipsram_init_struct->address_bits | + exmc_sqpipsram_init_struct->command_bits; +} + +/*! + \brief initialize the struct exmc_sqpipsram_parameter_struct + \param[in] the struct exmc_sqpipsram_parameter_struct pointer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +{ + /* configure the structure with default value */ + exmc_sqpipsram_init_struct->sample_polarity = EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE; + exmc_sqpipsram_init_struct->id_length = EXMC_SQPIPSRAM_ID_LENGTH_64B; + exmc_sqpipsram_init_struct->address_bits = EXMC_SQPIPSRAM_ADDR_LENGTH_24B; + exmc_sqpipsram_init_struct->command_bits = EXMC_SQPIPSRAM_COMMAND_LENGTH_8B; +} + +/*! + \brief set the read command + \param[in] read_command_mode: configure SPI PSRAM read command mode + \arg EXMC_SQPIPSRAM_READ_MODE_DISABLE: not SPI mode + \arg EXMC_SQPIPSRAM_READ_MODE_SPI: SPI mode + \arg EXMC_SQPIPSRAM_READ_MODE_SQPI: SQPI mode + \arg EXMC_SQPIPSRAM_READ_MODE_QPI: QPI mode + \param[in] read_wait_cycle: wait cycle number after address phase,0..15 + \param[in] read_command_code: read command for AHB read transfer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_wait_cycle, uint32_t read_command_code) +{ + uint32_t srcmd; + + srcmd = (uint32_t) read_command_mode | + ((read_wait_cycle << SRCMD_RWAITCYCLE_OFFSET) & EXMC_SRCMD_RWAITCYCLE) | + ((read_command_code & EXMC_SRCMD_RCMD)); + EXMC_SRCMD = srcmd; +} + +/*! + \brief set the write command + \param[in] write_command_mode: configure SPI PSRAM write command mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_DISABLE: not SPI mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_SPI: SPI mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_SQPI: SQPI mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_QPI: QPI mode + \param[in] write_wait_cycle: wait cycle number after address phase,0..15 + \param[in] write_command_code: write command for AHB write transfer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_write_command_set(uint32_t write_command_mode, uint32_t write_wait_cycle, uint32_t write_command_code) +{ + uint32_t swcmd; + + swcmd = (uint32_t) write_command_mode | + ((write_wait_cycle << SWCMD_WWAITCYCLE_OFFSET) & EXMC_SWCMD_WWAITCYCLE) | + ((write_command_code & EXMC_SWCMD_WCMD)); + EXMC_SWCMD = swcmd; +} + +/*! + \brief send SPI read ID command + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sqpipsram_read_id_command_send(void) +{ + EXMC_SRCMD |= EXMC_SRCMD_RDID; +} + +/*! + \brief send SPI special command which does not have address and data phase + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sqpipsram_write_cmd_send(void) +{ + EXMC_SWCMD |= EXMC_SWCMD_SC; +} + +/*! + \brief get the EXMC SPI ID low data + \param[in] none + \param[out] none + \retval the ID low data +*/ +uint32_t exmc_sqpipsram_low_id_get(void) +{ + return (EXMC_SIDL); +} + +/*! + \brief get the EXMC SPI ID high data + \param[in] none + \param[out] none + \retval the ID high data +*/ +uint32_t exmc_sqpipsram_high_id_get(void) +{ + return (EXMC_SIDH); +} + +/*! + \brief get the bit value of EXMC send write command bit or read ID command + \param[in] send_command_flag: the send command flag + \arg EXMC_SEND_COMMAND_FLAG_RDID: EXMC_SRCMD_RDID flag bit + \arg EXMC_SEND_COMMAND_FLAG_SC: EXMC_SWCMD_SC flag bit + \param[out] none + \retval the new value of send command flag +*/ +FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag) +{ + uint32_t flag = 0x00000000U; + + if(EXMC_SEND_COMMAND_FLAG_RDID == send_command_flag){ + flag = EXMC_SRCMD; + }else if(EXMC_SEND_COMMAND_FLAG_SC == send_command_flag){ + flag = EXMC_SWCMD; + }else{ + } + + if (flag & send_command_flag){ + /* flag is set */ + return SET; + }else{ + /* flag is reset */ + return RESET; + } +} + +/*! + \brief check EXMC flag is set or not + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC Card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] flag: specify get which flag + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \arg EXMC_SDRAM_FLAG_REFRESH: refresh error interrupt flag + \arg EXMC_SDRAM_FLAG_NREADY: not ready status + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag) +{ + uint32_t status = 0x00000000U; + + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + }else{ + /* SDRAM device0 or device1 */ + status = EXMC_SDSTAT; + } + + if((status & flag) != (uint32_t)flag){ + /* flag is reset */ + return RESET; + }else{ + /* flag is set */ + return SET; + } +} + +/*! + \brief clear EXMC flag + \param[in] bank: specifie the NAND bank , PCCARD bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] flag: specify get which flag + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \arg EXMC_SDRAM_FLAG_REFRESH: refresh error interrupt flag + \arg EXMC_SDRAM_FLAG_NREADY: not ready status + \param[out] none + \retval none +*/ +void exmc_flag_clear(uint32_t bank, uint32_t flag) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~flag; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDSTAT &= ~flag; + } +} + +/*! + \brief check EXMC interrupt flag is set or not + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source) +{ + uint32_t status = 0x00000000U, interrupt_enable = 0x00000000U, interrupt_state = 0x00000000U; + + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + interrupt_state = (status & (interrupt_source >> INTEN_INTS_OFFSET)); + }else{ + /* SDRAM device0 or device1 */ + status = EXMC_SDARI; + interrupt_state = (EXMC_SDSTAT & EXMC_SDSDAT_REIF); + } + + interrupt_enable = (status & interrupt_source); + + if ((interrupt_enable) && (interrupt_state)){ + /* interrupt flag is set */ + return SET; + }else{ + /* interrupt flag is reset */ + return RESET; + } +} + +/*! + \brief clear EXMC interrupt flag + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error + \param[out] none + \retval none +*/ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~(interrupt_source >> INTEN_INTS_OFFSET); + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI |= EXMC_SDARI_REC; + } +} + +/*! + \brief enable EXMC interrupt + \param[in] bank: specifies the NAND bank,PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) |= interrupt_source; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI |= EXMC_SDARI_REIE; + } +} + +/*! + \brief disable EXMC interrupt + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~interrupt_source; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI &= ~EXMC_SDARI_REIE; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c new file mode 100644 index 0000000000..26e29b7994 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c @@ -0,0 +1,255 @@ +/*! + \file gd32f20x_exti.c + \brief EXTI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_exti.h" + +#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none +*/ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = EXTI_REG_RESET_VALUE; + EXTI_EVEN = EXTI_REG_RESET_VALUE; + EXTI_RTEN = EXTI_REG_RESET_VALUE; + EXTI_FTEN = EXTI_REG_RESET_VALUE; + EXTI_SWIEV = EXTI_REG_RESET_VALUE; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling edge trigger + \arg EXTI_TRIG_BOTH: rising edge and falling edge trigger + \param[out] none + \retval none +*/ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN &= ~(uint32_t)linex; + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch(mode){ + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t)linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t)linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch(trig_type){ + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t)linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t)linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t)linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t)linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t)linex; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c new file mode 100644 index 0000000000..a2a55e4baf --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c @@ -0,0 +1,966 @@ +/*! + \file gd32f20x_fmc.c + \brief FMC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_fmc.h" + +/*! + \brief set the wait state counter value + \param[in] wscnt£ºwait state counter value + \arg WS_WSCNT_0: FMC 0 wait state + \arg WS_WSCNT_1: FMC 1 wait state + \arg WS_WSCNT_2: FMC 2 wait state + \param[out] none + \retval none +*/ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* write the FMC unlock key */ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } + } +} + +/*! + \brief unlock the FMC bank0 operation + this function can be used for all GD32F20x devices. + for GD32F20x with flash more than 512KB, this function unlocks bank0. + for GD32F20x with flash no more than 512KB and it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } +} + +/*! + \brief unlock the FMC bank1 operation + this function can be used for GD32F20x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_unlock(void) +{ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + /* write the FMC unlock key */ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL0 |= FMC_CTL0_LK; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* set the LK bit */ + FMC_CTL1 |= FMC_CTL1_LK; + } +} + +/*! + \brief lock the FMC bank0 operation + this function can be used for all GD32F20X devices. + for GD32F20x with flash more than 512KB, this function locks bank0. + for GD32F20x with flash no more than 512KB and it is equivalent to fmc_lock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_lock(void) +{ + /* set the LK bit*/ + FMC_CTL0 |= FMC_CTL0_LK; +} + +/*! + \brief lock the FMC bank1 operation + this function can be used for GD32F20x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_lock(void) +{ + /* set the LK bit*/ + FMC_CTL1 |= FMC_CTL1_LK; +} + +/*! + \brief erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > page_address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + }else{ + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL1 |= FMC_CTL1_PER; + FMC_ADDR1 = page_address; + if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + FMC_ADDR0 = page_address; + } + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL1 &= ~FMC_CTL1_PER; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase bank0 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank0 erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief erase bank1 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank1 erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } + + /* wait until OBWEN bit is set by hardware */ + while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL0 &= ~FMC_CTL0_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL0 and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + /* no security protection */ + OB_SPC = (uint16_t)temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if + you want to protect the corresponding pages. meanwhile, sector + macro could used to set specific sector write protected. + one or more parameters can be selected which are shown as below: + \arg OB_WPx(x = 0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t)(~ob_wp); + temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + only one parameter can be selected which is shown as below: + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + + /* start the option byte program */ + FMC_CTL0 |= FMC_CTL0_OBPG; + + OB_SPC = (uint16_t)ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t)temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program option bytes data + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC user option byte + \param[in] none + \param[out] none + \retval the FMC user option byte values +*/ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t)(FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data +*/ +uint16_t ob_data_get(void) +{ + return (uint16_t)(FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value +*/ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get the FMC option byte security protection + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit + \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval none +*/ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + FlagStatus ret1 = RESET; + FlagStatus ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); + }else{ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval none +*/ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC bank0 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC bank1 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ + fmc_state = FMC_PGERR; + } + } + } + + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank0 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank0_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank1 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank1_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c new file mode 100644 index 0000000000..be51942db7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c @@ -0,0 +1,158 @@ +/*! + \file gd32f20x_fwdgt.c + \brief FWDGT driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + FWDGT_RLD = RLD_RLD(reload_value); + + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(FWDGT_STAT & flag){ + return SET; + } + + return RESET; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c new file mode 100644 index 0000000000..b5c1de1eaa --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c @@ -0,0 +1,726 @@ +/*! + \file gd32f20x_gpio.c + \brief GPIO driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch(gpio_periph){ + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + case GPIOF: + /* reset GPIOF */ + rcu_periph_reset_enable(RCU_GPIOFRST); + rcu_periph_reset_disable(RCU_GPIOFRST); + break; + case GPIOG: + /* reset GPIOG */ + rcu_periph_reset_enable(RCU_GPIOGRST); + rcu_periph_reset_disable(RCU_GPIOGRST); + break; + case GPIOH: + /* reset GPIOH */ + rcu_periph_reset_enable(RCU_GPIOHRST); + rcu_periph_reset_disable(RCU_GPIOHRST); + break; + case GPIOI: + /* reset GPIOI */ + rcu_periph_reset_enable(RCU_GPIOIRST); + rcu_periph_reset_disable(RCU_GPIOIRST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); + + /* GPIO speed configuration */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t)speed; + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for(i = 0U;i < 8U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for(i = 8U;i < 16U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) +{ + if(RESET != bit_value){ + GPIO_BOP(gpio_periph) = (uint32_t)pin; + }else{ + GPIO_BC(gpio_periph) = (uint32_t)pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph,uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t)data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t)(GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t)GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping + \arg GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping + \arg GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping + \arg GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping + \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping + \arg GPIO_ENET_REMAP: ENET remapping + \arg GPIO_CAN1_REMAP: CAN1 remapping + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping + \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping + \arg GPIO_TIMER8_REMAP: TIMER8 remapping + \arg GPIO_TIMER9_REMAP: TIMER9 remapping + \arg GPIO_TIMER10_REMAP: TIMER10 remapping + \arg GPIO_TIMER12_REMAP: TIMER12 remapping + \arg GPIO_TIMER13_REMAP: TIMER13 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if(AFIO_PCF1_FIELDS == (gpio_remap & AFIO_PCF1_FIELDS)){ + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + }else{ + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (gpio_remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = gpio_remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (gpio_remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + }else if(PCF_LOCATION2_MASK == (gpio_remap & PCF_LOCATION2_MASK)){ + remap2 = ((uint32_t)0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + }else{ + temp_reg &= ~(remap1 << ((gpio_remap >> 0x15U)*0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if(DISABLE != newvalue){ + temp_reg |= (remap1 << ((gpio_remap >> 0x15U)*0x10U)); + } + + if(AFIO_PCF1_FIELDS == (gpio_remap & AFIO_PCF1_FIELDS)){ + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + }else{ + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +/*! + \brief configure GPIO pin remap1 + \param[in] remap_reg: + \arg GPIO_PCF2: AFIO port configuration register 2 + \arg GPIO_PCF3: AFIO port configuration register 3 + \arg GPIO_PCF4: AFIO port configuration register 4 + \arg GPIO_PCF5: AFIO port configuration register 5 + \param[in] remap: select the pin to remap + \arg GPIO_PCF2_DCI_VSYNC_PG9_REMAP: DCI VSYNC remapped to PG9 + \arg GPIO_PCF2_DCI_VSYNC_PI5_REMAP: DCI VSYNC remapped to PI5 + \arg GPIO_PCF2_DCI_D0_PC6_REMAP: DCI D0 remapped to PC6 + \arg GPIO_PCF2_DCI_D0_PH9_REMAP: DCI D0 remapped to PH9 + \arg GPIO_PCF2_DCI_D1_PC7_REMAP: DCI D1 remapped to PC7 + \arg GPIO_PCF2_DCI_D1_PH10_REMAP: DCI D1 remapped to PH10 + \arg GPIO_PCF2_DCI_D2_PE0_REMAP: DCI D2 remapped to PE0 + \arg GPIO_PCF2_DCI_D2_PG10_REMAP: DCI D2 remapped to PG10 + \arg GPIO_PCF2_DCI_D2_PH11_REMAP: DCI D2 remapped to PH11 + \arg GPIO_PCF2_DCI_D3_PE1_REMAP: DCI D3 remapped to PE1 + \arg GPIO_PCF2_DCI_D3_PG11_REMAP: DCI D3 remapped to PG11 + \arg GPIO_PCF2_DCI_D3_PH12_REMAP: DCI D3 remapped to PH12 + \arg GPIO_PCF2_DCI_D4_PE4_REMAP: DCI D4 remapped to PE4 + \arg GPIO_PCF2_DCI_D4_PH14_REMAP: DCI D4 remapped to PH14 + \arg GPIO_PCF2_DCI_D5_PD3_REMAP: DCI D5 remapped to PD3 + \arg GPIO_PCF2_DCI_D5_PI4_REMAP: DCI D5 remapped to PI4 + \arg GPIO_PCF2_DCI_D6_PE5_REMAP: DCI D6 remapped to PE5 + \arg GPIO_PCF2_DCI_D6_PI6_REMAP: DCI D6 remapped to PI6 + \arg GPIO_PCF2_DCI_D7_PE6_REMAP: DCI D7 remapped to PE6 + \arg GPIO_PCF2_DCI_D7_PI7_REMAP: DCI D7 remapped to PI7 + \arg GPIO_PCF2_DCI_D8_PH6_REMAP: DCI D8 remapped to PH6 + \arg GPIO_PCF2_DCI_D8_PI1_REMAP: DCI D8 remapped to PI1 + \arg GPIO_PCF2_DCI_D9_PH7_REMAP: DCI D9 remapped to PH7 + \arg GPIO_PCF2_DCI_D9_PI2_REMAP: DCI D9 remapped to PI2 + \arg GPIO_PCF2_DCI_D10_PD6_REMAP: DCI D10 remapped to PD6 + \arg GPIO_PCF2_DCI_D10_PI3_REMAP: DCI D10 remapped to PI3 + \arg GPIO_PCF2_DCI_D11_PF10_REMAP: DCI D11 remapped to PF10 + \arg GPIO_PCF2_DCI_D11_PH15_REMAP: DCI D11 remapped to PH15 + \arg GPIO_PCF2_DCI_D12_PG6_REMAP: DCI D12 remapped to PG6 + \arg GPIO_PCF2_DCI_D13_PG15_REMAP: DCI D12 remapped to PG15 + \arg GPIO_PCF2_DCI_D13_PI0_REMAP: DCI D13 remapped to PI0 + \arg GPIO_PCF2_DCI_HSYNC_PH8_REMAP: DCI HSYNC to PH8 + \arg GPIO_PCF2_PH01_REMAP: PH0/PH1 remapping + \arg GPIO_PCF3_TLI_B5_PA3_REMAP: TLI B5 remapped to PA3 + \arg GPIO_PCF3_TLI_VSYNC_PA4_REMAP: TLI VSYNC remapped to PA4 + \arg GPIO_PCF3_TLI_G2_PA6_REMAP: TLI G2 remapped to PA6 + \arg GPIO_PCF3_TLI_R6_PA8_REMAP: TLI R6 remapped to PA8 + \arg GPIO_PCF3_TLI_R4_PA11_REMAP: TLI R4 remapped to PA11 + \arg GPIO_PCF3_TLI_R5_PA12_REMAP: TLI R5 remapped to PA12 + \arg GPIO_PCF3_TLI_R3_PB0_REMAP: TLI R3 remapped to PB0 + \arg GPIO_PCF3_TLI_R6_PB1_REMAP: TLI R6 remapped to PB1 + \arg GPIO_PCF3_TLI_B6_PB8_REMAP: TLI B6 remapped to PB8 + \arg GPIO_PCF3_TLI_B7_PB9_REMAP: TLI B7 remapped to PB9 + \arg GPIO_PCF3_TLI_G4_PB10_REMAP: TLI G4 remapped to PB10 + \arg GPIO_PCF3_TLI_G5_PB11_REMAP: TLI G5 remapped to PB11 + \arg GPIO_PCF3_TLI_HSYNC_PC6_REMAP: TLI HSYNC remapped to PC6 + \arg GPIO_PCF3_TLI_G6_PC7_REMAP: TLI G6 remapped to PC7 + \arg GPIO_PCF3_TLI_R2_PC10_REMAP: TLI R2 remapped to PC10 + \arg GPIO_PCF3_TLI_G7_PD3_REMAP: TLI G7 remapped to PD3 + \arg GPIO_PCF3_TLI_B2_PD6_REMAP: TLI B2 remapped to PD6 + \arg GPIO_PCF3_TLI_B3_PD10_REMAP: TLI B3 remapped to PD10 + \arg GPIO_PCF3_TLI_B0_PE4_REMAP: TLI B0 remapped to PE4 + \arg GPIO_PCF3_TLI_G0_PE5_REMAP: TLI G0 remapped to PE5 + \arg GPIO_PCF3_TLI_G1_PE6_REMAP: TLI G1 remapped to PE6 + \arg GPIO_PCF3_TLI_G3_PE11_REMAP: TLI G3 remapped to PE11 + \arg GPIO_PCF3_TLI_B4_PE12_REMAP: TLI B4 remapped to PE12 + \arg GPIO_PCF3_TLI_DE_PE13_REMAP: TLI DE remapped to PE13 + \arg GPIO_PCF3_TLI_CLK_PE14_REMAP: TLI CLK remapped to PE14 + \arg GPIO_PCF3_TLI_R7_PE15_REMAP: TLI R7 remapped to PE15 + \arg GPIO_PCF3_TLI_DE_PF10_REMAP: TLI DE remapped to PF10 + \arg GPIO_PCF3_TLI_R7_PG6_REMAP: TLI R7 remapped to PG6 + \arg GPIO_PCF3_TLI_CLK_PG7_REMAP: TLI CLK remapped to PG7 + \arg GPIO_PCF3_TLI_G3_PG10_REMAP: TLI G3 remapped to PG10 + \arg GPIO_PCF3_TLI_B2_PG10_REMAP: TLI B2 remapped to PG10 + \arg GPIO_PCF3_TLI_B3_PG11_REMAP: TLI B3 remapped to PG11 + \arg GPIO_PCF4_TLI_B4_PG12_REMAP: B4 remapped to PG12 + \arg GPIO_PCF4_TLI_B1_PG12_REMAP: B1 remapped to PG12 + \arg GPIO_PCF4_TLI_R0_PH2_REMAP2: R0 remapped to PH2 + \arg GPIO_PCF4_TLI_R1_PH3_REMAP: TLI R1 remapped to PH3 + \arg GPIO_PCF4_TLI_R2_PH8_REMAP: TLI R2 remapped to PH8 + \arg GPIO_PCF4_TLI_R3_PH9_REMAP: TLI R3 remapped to PH9 + \arg GPIO_PCF4_TLI_R4_PH10_REMAP: TLI R4 remapped to PH10 + \arg GPIO_PCF4_TLI_R5_PH11_REMAP: TLI R5 remapped to PH11 + \arg GPIO_PCF4_TLI_R6_PH12_REMAP: TLI R6 remapped to PH12 + \arg GPIO_PCF4_TLI_G2_PH13_REMAP: TLI G2 remapped to PH13 + \arg GPIO_PCF4_TLI_G3_PH14_REMAP: TLI G3 remapped to PH14 + \arg GPIO_PCF4_TLI_G4_PH15_REMAP: TLI G4 remapped to PH15 + \arg GPIO_PCF4_TLI_G5_PI0_REMAP: TLI G5 remapped to PI0 + \arg GPIO_PCF4_TLI_G6_PI1_REMAP: TLI G6 remapped to PI1 + \arg GPIO_PCF4_TLI_G7_PI2_REMAP: TLI G7 remapped to PI2 + \arg GPIO_PCF4_TLI_B4_PI4_REMAP: TLI B4 remapped to PI4 + \arg GPIO_PCF4_TLI_B5_PI5_REMAP: TLI B5 remapped to PI5 + \arg GPIO_PCF4_TLI_B6_PI6_REMAP: TLI B6 remapped to PI6 + \arg GPIO_PCF4_TLI_B7_PI7_REMAP: TLI B7 remapped to PI7 + \arg GPIO_PCF4_TLI_VSYNC_PI9_REMAP: TLI VSYNC remapped to PI9 + \arg GPIO_PCF4_TLI_HSYNC_PI10_REMAP: TLI HSYNC remapped to PI10 + \arg GPIO_PCF4_TLI_R0_PH4_REMAP: TLI R0 remapped to PH4 + \arg GPIO_PCF4_TLI_R1_PI3_REMAP: TLI R1 remapped to PI3 + \arg GPIO_PCF4_SPI1_SCK_PD3_REMAP: SPI1 SCK remapped to PD3 + \arg GPIO_PCF4_SPI2_MOSI_PD6_REMAP: SPI2 MOSI remapped to PD6 + \arg GPIO_PCF5_I2C2_REMAP0: I2C2 remapping 0 + \arg GPIO_PCF5_I2C2_REMAP1: I2C2 remapping 1 + \arg GPIO_PCF5_TIMER1_CH0_REMAP: TIMER1 CH0 remapped to PA5 + \arg GPIO_PCF5_TIMER4_REMAP: TIMER4 CH0 remapping + \arg GPIO_PCF5_TIMER7_CHON_REMAP0: TIMER7 CHON remapping 0 + \arg GPIO_PCF5_TIMER7_CHON_REMAP1: TIMER7 CHON remapping 1 + \arg GPIO_PCF5_TIMER7_CH_REMAP: TIMER7 CH remapping + \arg GPIO_PCF5_I2C1_REMAP0: I2C1 remapping 0 + \arg GPIO_PCF5_I2C1_REMAP1: I2C1 remapping 1 + \arg GPIO_PCF5_SPI1_NSCK_REMAP0: SPI1 NSS/SCK remapping 0 + \arg GPIO_PCF5_SPI1_NSCK_REMAP1: SPI1 NSS/SCK remapping 1 + \arg GPIO_PCF5_SPI1_IO_REMAP0: SPI1 MISO/MOSI remapping 0 + \arg GPIO_PCF5_SPI1_IO_REMAP1: SPI1 MISO/MOSI remapping 1 + \arg GPIO_PCF5_UART3_REMAP: UART3 remapping + \arg GPIO_PCF5_TIMER11_REMAP: TIMER11 remapping + \arg GPIO_PCF5_CAN0_ADD_REMAP: CAN0 addition remapping + \arg GPIO_PCF5_ENET_TXD3_REMAP: ETH_TXD3 remapped to PE2 + \arg GPIO_PCF5_PPS_HI_REMAP: ETH_PPS_OUT remapped to PG8 + \arg GPIO_PCF5_ENET_TXD01_REMAP: ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping + \arg GPIO_PCF5_ENET_CRSCOL_REMAP: ETH_MII_CRS/ETH_MII_COL remapping + \arg GPIO_PCF5_ENET_RX_HI_REMAP: ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping + \arg GPIO_PCF5_UART6_REMAP: UART6 remapping + \arg GPIO_PCF5_USART5_CK_PG7_REMAP: USART5 CK remapped to PG7 + \arg GPIO_PCF5_USART5_RTS_PG12_REMAP: USART5 RTS remapped to PG12 + \arg GPIO_PCF5_USART5_CTS_PG13_REMAP: USART5 CTS remapped to PG13 + \arg GPIO_PCF5_USART5_TX_PG14_REMAP: USART5 TX remapped to PG14 + \arg GPIO_PCF5_USART5_RX_PG9_REMAP: USART5 RX remapped to PG9 + \arg GPIO_PCF5_EXMC_SDNWE_PC0_REMAP: EXMC SDNWE remapped to PC0 + \arg GPIO_PCF5_EXMC_SDCKE0_PC3_REMAP: EXMC SDCKE0 remapped to PC3 + \arg GPIO_PCF5_EXMC_SDCKE1_PB5_REMAP: EXMC SDCKE1 remapped to PB5 + \arg GPIO_PCF5_EXMC_SDNE0_PC2_REMAP: EXMC SDNE0 remapped to PC2 + \arg GPIO_PCF5_EXMC_SDNE1_PB6_REMAP: EXMC SDNE1 remapped to PB6 + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap1_config(uint8_t remap_reg, uint32_t remap, ControlStatus newvalue) +{ + uint32_t reg = 0U; + + if(DISABLE != newvalue){ + /* AFIO port configuration register selection */ + if(GPIO_PCF2 == remap_reg){ + reg = AFIO_PCF2; + reg |= remap; + AFIO_PCF2 = reg; + }else if(GPIO_PCF3 == remap_reg){ + reg = AFIO_PCF3; + reg |= remap; + AFIO_PCF3 = reg; + }else if(GPIO_PCF4 == remap_reg){ + reg = AFIO_PCF4; + reg |= remap; + AFIO_PCF4 = reg; + }else if(GPIO_PCF5 == remap_reg){ + reg = AFIO_PCF5; + reg |= remap; + AFIO_PCF5 = reg; + }else{ + /* illegal parameters */ + } + }else{ + if(GPIO_PCF2 == remap_reg){ + reg = AFIO_PCF2; + reg &= ~remap; + AFIO_PCF2 = reg; + }else if(GPIO_PCF3 == remap_reg){ + reg = AFIO_PCF3; + reg &= ~remap; + AFIO_PCF3 = reg; + }else if(GPIO_PCF4 == remap_reg){ + reg = AFIO_PCF4; + reg &= ~remap; + AFIO_PCF4 = reg; + }else if(GPIO_PCF5 == remap_reg){ + reg = AFIO_PCF5; + reg &= ~remap; + AFIO_PCF5 = reg; + }else{ + /* illegal parameters */ + } + } +} + +/*! + \brief select GPIO pin exti sources + \param[in] output_port: gpio event output port + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOF: output port source F + \arg GPIO_PORT_SOURCE_GPIOG: output port source G + \arg GPIO_PORT_SOURCE_GPIOH: output port source H + \arg GPIO_PORT_SOURCE_GPIOI: output port source I + \param[in] output_pin: GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if(GPIO_PIN_SOURCE_4 > output_pin){ + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_8 > output_pin){ + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_12 > output_pin){ + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else{ + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \param[in] output_pin: + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); + + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t)output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + GPIO_LOCK(gpio_periph) = (uint32_t)pin; + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} + +/*! + \brief select ethernet MII or RMII PHY + \param[in] enet_sel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t enet_sel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)enet_sel; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c new file mode 100644 index 0000000000..429a2382e7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c @@ -0,0 +1,331 @@ +/*! + \file gd32f20x_cau.c + \brief CAU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_hau.h" +#include "gd32f20x_rcu.h" + +/*! + \brief reset the HAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void hau_deinit(void) +{ + /* enable HAU reset state */ + rcu_periph_reset_enable(RCU_HAURST); + /* release HAU from reset state */ + rcu_periph_reset_disable(RCU_HAURST); +} + +/*! + \brief initialize the HAU peripheral parameters + \param[in] initpara: HAU init parameter struct + members of the structure and the member values are shown as below: + algo: HAU_ALGO_SHA1, HAU_ALGO_SHA224, HAU_ALGO_SHA256, HAU_ALGO_MD5 + mode: HAU_MODE_HASH, HAU_MODE_HMAC + datatype: HAU_SWAPPING_32BIT, HAU_SWAPPING_16BIT, HAU_SWAPPING_8BIT, HAU_SWAPPING_1BIT + keytype: HAU_KEY_SHORTER_64, HAU_KEY_LONGGER_64 + \param[out] none + \retval none +*/ +void hau_init(hau_init_parameter_struct* initpara) +{ + /* configure the algorithm, mode and the data type */ + HAU_CTL &= ~(HAU_CTL_ALGM_0 | HAU_CTL_ALGM_1 | HAU_CTL_DATAM | HAU_CTL_HMS); + HAU_CTL |= (initpara->algo | initpara->datatype | initpara->mode); + + /* when mode is HMAC, set the key */ + if(HAU_MODE_HMAC == initpara->mode){ + HAU_CTL &= ~HAU_CTL_KLM; + HAU_CTL |= initpara->keytype; + } + + /* start the digest of a new message */ + HAU_CTL |= HAU_CTL_START; +} + +/*! + \brief initialize the sturct hau_initpara + \param[in] initpara: HAU init parameter struct + members of the structure and the member values are shown as below: + algo: HAU_ALGO_SHA1, HAU_ALGO_SHA224, HAU_ALGO_SHA256, HAU_ALGO_MD5 + mode: HAU_MODE_HASH, HAU_MODE_HMAC + datatype: HAU_SWAPPING_32BIT, HAU_SWAPPING_16BIT, HAU_SWAPPING_8BIT, HAU_SWAPPING_1BIT + keytype: HAU_KEY_SHORTER_64, HAU_KEY_LONGGER_64 + \param[out] none + \retval none +*/ +void hau_init_parameter_init(hau_init_parameter_struct* initpara) +{ + initpara->algo = HAU_ALGO_SHA1; + initpara->mode = HAU_MODE_HASH; + initpara->datatype = HAU_SWAPPING_32BIT; + initpara->keytype = HAU_KEY_SHORTER_64; +} + +/*! + \brief reset the HAU processor core + \param[in] none + \param[out] none + \retval none +*/ +void hau_reset(void) +{ + /* set to 1 to reset the HAU processor core, then it is ready to start the digest calculation */ + HAU_CTL |= HAU_CTL_START; +} + +/*! + \brief configure the number of valid bits in last word of the message + \param[in] valid_num: number of valid bits in last word of the message + \arg 0x00: all 32 bits of the last data written are valid + \arg 0x01: only bit [31] of the last data written to HAU_DI after data swapping are valid + \arg 0x02: only bits [31:30] of the last data written to HAU_DI after data swapping are valid + \arg 0x03: only bits [31:29] of the last data written to HAU_DI after data swapping are valid + ... + \arg 0x1F: only bit [0] of the last data written to HAU_DI after data swapping are valid + \param[out] none + \retval none +*/ +void hau_last_word_validbits_num_config(uint32_t valid_num) +{ + HAU_CFG &= ~(HAU_CFG_VBL); + HAU_CFG |= CFG_VBL(valid_num); +} + +/*! + \brief write data to the IN FIFO + \param[in] data: data to write + \param[out] none + \retval none +*/ +void hau_data_write(uint32_t data) +{ + HAU_DI = data; +} + +/*! + \brief return the number of words already written into the IN FIFO + \param[in] none + \param[out] none + \retval number of words in the input FIFO +*/ +uint32_t hau_infifo_words_num_get(void) +{ + uint32_t ret = 0U; + ret = GET_CTL_NWIF(HAU_CTL); + return ret; +} + +/*! + \brief read the message digest result + \param[in] none + \param[out] digestpara: HAU digest parameter struct + out[7:0]: message digest result 0-7 + \retval none +*/ +void hau_digest_read(hau_digest_parameter_struct* digestpara) +{ + digestpara->out[0] = HAU_DO0; + digestpara->out[1] = HAU_DO1; + digestpara->out[2] = HAU_DO2; + digestpara->out[3] = HAU_DO3; + digestpara->out[4] = HAU_DO4; + digestpara->out[5] = HAU_DO5; + digestpara->out[6] = HAU_DO6; + digestpara->out[7] = HAU_DO7; +} + +/*! + \brief enable digest calculation + \param[in] none + \param[out] none + \retval none +*/ +void hau_digest_calculation_enable(void) +{ + HAU_CFG |= HAU_CFG_CALEN; +} + +/*! + \brief configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not + \param[in] multi_single + only one parameter can be selected which is shown as below + \arg SINGLE_DMA_AUTO_DIGEST: message padding and message digest calculation at the end of a DMA transfer + \arg MULTIPLE_DMA_NO_DIGEST: multiple DMA transfers needed and CALEN bit is not automatically set at the end of a DMA transfer + \param[out] none + \retval none +*/ +void hau_multiple_single_dma_config(uint32_t multi_single) +{ + HAU_CTL &= ~HAU_CTL_MDS; + HAU_CTL |= multi_single; +} + +/*! + \brief enable the HAU DMA interface + \param[in] none + \param[out] none + \retval none +*/ +void hau_dma_enable(void) +{ + HAU_CTL |= HAU_CTL_DMAE; +} + +/*! + \brief disable the HAU DMA interface + \param[in] none + \param[out] none + \retval none +*/ +void hau_dma_disable(void) +{ + HAU_CTL &= ~HAU_CTL_DMAE; +} + +/*! + \brief get the HAU flag status + \param[in] flag: HAU flag status + only one parameter can be selected which is shown as below + \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \arg HAU_FLAG_DMA: DMA is enabled (DMAE =1) or a transfer is processing + \arg HAU_FLAG_BUSY: data block is in process + \arg HAU_FLAG_INFIFO_NO_EMPTY: the input FIFO is not empty + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus hau_flag_get(uint32_t flag) +{ + uint32_t ret = 0U; + FlagStatus ret_flag = RESET; + + /* check if the flag is in HAU_CTL register */ + if(RESET != (flag & HAU_FLAG_INFIFO_NO_EMPTY)){ + ret = HAU_CTL; + }else{ + ret = HAU_STAT; + } + + if (RESET != (ret & flag)){ + ret_flag = SET; + } + + return ret_flag; +} + +/*! + \brief clear the HAU flag status + \param[in] flag: HAU flag status + one or more parameters can be selected which are shown as below + \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \param[out] none + \retval none +*/ +void hau_flag_clear(uint32_t flag) +{ + HAU_STAT = ~(uint32_t)(flag); +} + +/*! + \brief enable the HAU interrupts + \param[in] interrupt: specify the HAU interrupt source to be enabled + one or more parameters can be selected which are shown as below + \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer + \arg HAU_INT_CALCULATION_COMPLETE: calculation complete + \param[out] none + \retval none +*/ +void hau_interrupt_enable(uint32_t interrupt) +{ + HAU_INTEN |= interrupt; +} + +/*! + \brief disable the HAU interrupts + \param[in] interrupt: specify the HAU interrupt source to be disabled + one or more parameters can be selected which are shown as below + \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer + \arg HAU_INT_CALCULATION_COMPLETE: calculation complete + \param[out] none + \retval none +*/ +void hau_interrupt_disable(uint32_t interrupt) +{ + HAU_INTEN &= ~(uint32_t)(interrupt); +} + +/*! + \brief get the HAU interrupt flag status + \param[in] int_flag: HAU interrupt flag status + only one parameter can be selected which is shown as below + \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_INT_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus hau_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t ret = 0U; + FlagStatus flag = RESET; + + /* return the status of the interrupt */ + ret = HAU_STAT; + + if(RESET != ((HAU_INTEN & ret) & int_flag)){ + flag = SET; + } + + return flag; +} + +/*! + \brief clear the HAU interrupt flag status + \param[in] int_flag: HAU interrupt flag status + one or more parameters can be selected which are shown as below + \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_INT_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \param[out] none + \retval none +*/ +void hau_interrupt_flag_clear(uint32_t int_flag) +{ + HAU_STAT = ~(uint32_t)(int_flag); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c new file mode 100644 index 0000000000..b22cd8f545 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c @@ -0,0 +1,422 @@ +/*! + \file gd32f20x_hau_sha_md5.c + \brief HAU_SHA_MD5 driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_hau.h" + +#define SHAMD5_BSY_TIMEOUT ((uint32_t)0x00010000U) + +/* HAU SHA/MD5 digest read in HASH mode */ +static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output); +/* HAU digest calculate process in HASH mode */ +static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output); +/* HAU digest calculate process in HMAC mode */ +static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief calculate digest using SHA1 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_sha_1(uint8_t *input, uint32_t in_length, uint8_t output[20]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_SHA1, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA1 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_sha_1(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[20]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_SHA1, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA224 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_sha_224(uint8_t *input, uint32_t in_length, uint8_t output[28]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_SHA224, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA224 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_sha_224(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[28]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_SHA224, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA256 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_sha_256(uint8_t *input, uint32_t in_length, uint8_t output[32]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_SHA256, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA256 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_sha_256(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[32]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_SHA256, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using MD5 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_md5(uint8_t *input, uint32_t in_length, uint8_t output[16]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_MD5, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using MD5 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_md5(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[16]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_MD5, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief HAU SHA/MD5 digest read + \param[in] algo: algorithm selection + \param[out] output: the result digest + \retval none +*/ +static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output) +{ + hau_digest_parameter_struct digest_para; + uint32_t outputaddr = (uint32_t)output; + + switch(algo){ + case HAU_ALGO_SHA1: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + break; + case HAU_ALGO_SHA224: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[5]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[6]); + break; + case HAU_ALGO_SHA256: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[5]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[6]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[7]); + break; + case HAU_ALGO_MD5: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + break; + default: + break; + } +} + +/*! + \brief HAU digest calculate process in HASH mode + \param[in] algo: algorithm selection + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output) +{ + hau_init_parameter_struct init_para; + + __IO uint32_t num_last_valid = 0U; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + uint32_t inputaddr = (uint32_t)input; + + /* number of valid bits in last word */ + num_last_valid = 8U * (in_length % 4U); + + /* HAU peripheral initialization */ + hau_deinit(); + + /* HAU configuration */ + init_para.algo = algo; + init_para.mode = HAU_MODE_HASH; + init_para.datatype = HAU_SWAPPING_8BIT; + hau_init(&init_para); + + /* configure the number of valid bits in last word of the message */ + hau_last_word_validbits_num_config(num_last_valid); + + /* write data to the IN FIFO */ + for(i = 0U; i < in_length; i += 4U){ + hau_data_write(*(uint32_t*)inputaddr); + inputaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the message digest */ + hau_sha_md5_digest_read(algo, output); + } + return SUCCESS; +} + +/*! + \brief HAU digest calculate process in HMAC mode + \param[in] algo: algorithm selection + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t *output) +{ + hau_init_parameter_struct init_para; + + __IO uint16_t num_last_valid = 0U; + __IO uint16_t num_key_valid = 0U; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + uint32_t keyaddr = (uint32_t)key; + uint32_t inputaddr = (uint32_t)input; + + /* number of valid bits in last word of the message */ + num_last_valid = 8U * (uint16_t)(in_length % 4U); + /* number of valid bits in last word of the key */ + num_key_valid = 8U * (uint16_t)(keysize % 4U); + + /* HAU peripheral initialization */ + hau_deinit(); + + /* HAU configuration */ + init_para.algo = algo; + init_para.mode = HAU_MODE_HMAC; + init_para.datatype = HAU_SWAPPING_8BIT; + if(keysize > 64U){ + init_para.keytype = HAU_KEY_LONGGER_64; + }else{ + init_para.keytype = HAU_KEY_SHORTER_64; + } + hau_init(&init_para); + + /* configure the number of valid bits in last word of the key */ + hau_last_word_validbits_num_config((uint32_t)num_key_valid); + + /* write the key */ + for(i = 0U; i < keysize; i += 4U){ + hau_data_write(*(uint32_t*)keyaddr); + keyaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* configure the number of valid bits in last word of the message */ + hau_last_word_validbits_num_config((uint32_t)num_last_valid); + + /* write data to the IN FIFO */ + for(i = 0U; i < in_length; i += 4U){ + hau_data_write(*(uint32_t*)inputaddr); + inputaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + counter = 0U; + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* configure the number of valid bits in last word of the key */ + hau_last_word_validbits_num_config((uint32_t)num_key_valid); + + /* write the key */ + keyaddr = (uint32_t)key; + for(i = 0U; i < keysize; i += 4U){ + hau_data_write(*(uint32_t*)keyaddr); + keyaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + counter =0U; + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the message digest */ + hau_sha_md5_digest_read(algo, output); + } + } + } + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c new file mode 100644 index 0000000000..fe5af0c6fd --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c @@ -0,0 +1,720 @@ +/*! + \file gd32f20x_i2c.c + \brief I2C driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-04-16, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_i2c.h" + +/* I2C register bit mask */ +#define I2CCLK_MAX ((uint32_t)0x0000003FU) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_deinit(uint32_t i2c_periph) +{ + switch(i2c_periph){ + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + case I2C2: + /* reset I2C2 */ + rcu_periph_reset_enable(RCU_I2C2RST); + rcu_periph_reset_disable(RCU_I2C2RST); + break; + default: + break; + + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none +*/ +void i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc) +{ + uint32_t pclk1,clkc,freq,risetime; + uint32_t temp; + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if(100000U >= clkspeed){ + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t)((pclk1/1000000U)+1U); + if(risetime >= I2CCLK_MAX){ + I2C_RT(i2c_periph) = I2CCLK_MAX; + }else if(risetime <= I2CCLK_MIN){ + I2C_RT(i2c_periph) = I2CCLK_MIN; + }else{ + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t)(pclk1/(clkspeed*2U)); + if(clkc < 0x04U){ + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + }else{ + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] mod: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none +*/ +void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t mode,uint32_t addformat,uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none +*/ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if(I2C_SMBUS_HOST == type){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none +*/ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none +*/ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) +{ + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval data of received +*/ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none +*/ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none +*/ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none +*/ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_DISSTRC); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none +*/ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none +*/ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none +*/ +void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none +*/ +void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval PEC value +*/ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t)((I2C_STAT1(i2c_periph) &I2C_STAT1_ECV) >> STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none +*/ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none +*/ +void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none +*/ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] intflag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c new file mode 100644 index 0000000000..9ddb9e97ed --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c @@ -0,0 +1,186 @@ +/*! + \file gd32f20x_misc.c + \brief MISC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_misc.h" + +/*! + \brief set the priority group + \param[in] nvic_prigroup: the NVIC priority group + \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \param[out] none + \retval none +*/ +void nvic_priority_group_set(uint32_t nvic_prigroup) +{ + /* set the priority group value */ + SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; +} + +/*! + \brief enable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set + \param[in] nvic_irq_sub_priority: the subpriority needed to set + \param[out] none + \retval none +*/ +void nvic_irq_enable(uint8_t nvic_irq, + uint8_t nvic_irq_pre_priority, + uint8_t nvic_irq_sub_priority) +{ + uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; + + /* use the priority group value to get the temp_pre and the temp_sub */ + switch ((SCB->AIRCR) & (uint32_t)0x700U) { + case NVIC_PRIGROUP_PRE0_SUB4: + temp_pre = 0U; + temp_sub = 0x4U; + break; + case NVIC_PRIGROUP_PRE1_SUB3: + temp_pre = 1U; + temp_sub = 0x3U; + break; + case NVIC_PRIGROUP_PRE2_SUB2: + temp_pre = 2U; + temp_sub = 0x2U; + break; + case NVIC_PRIGROUP_PRE3_SUB1: + temp_pre = 3U; + temp_sub = 0x1U; + break; + case NVIC_PRIGROUP_PRE4_SUB0: + temp_pre = 4U; + temp_sub = 0x0U; + break; + default: + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre = 2U; + temp_sub = 0x2U; + break; + } + + /* get the temp_priority to fill the NVIC->IP register */ + temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); + temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority = temp_priority << 0x04U; + NVIC->IP[nvic_irq] = (uint8_t)temp_priority; + + /* enable the selected IRQ */ + NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief disable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void nvic_irq_disable(uint8_t nvic_irq) +{ + /* disable the selected IRQ.*/ + NVIC->ICER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief set the NVIC vector table base address + \param[in] nvic_vict_tab: the RAM or FLASH base address + \arg NVIC_VECTTAB_RAM: RAM base address + \are NVIC_VECTTAB_FLASH: Flash base address + \param[in] offset: Vector Table offset + \param[out] none + \retval none +*/ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) +{ + SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); +} + +/*! + \brief set the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + by all the enable and disable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_set(uint8_t lowpower_mode) +{ + SCB->SCR |= (uint32_t)lowpower_mode; +} + +/*! + \brief reset the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + woke up by the enable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_reset(uint8_t lowpower_mode) +{ + SCB->SCR &= (~(uint32_t)lowpower_mode); +} + +/*! + \brief set the systick clock source + \param[in] systick_clksource: the systick clock source needed to choose + \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK + \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 + \param[out] none + \retval none +*/ + +void systick_clksource_set(uint32_t systick_clksource) +{ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + /* set the systick clock source from HCLK */ + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + }else{ + /* set the systick clock source from HCLK/8 */ + SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c new file mode 100644 index 0000000000..2010191bbc --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c @@ -0,0 +1,281 @@ +/*! + \file gd32f20x_pmu.c + \brief PMU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_pmu.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + only one parameter can be selected which is shown as below: + \arg PMU_LVDT_0: voltage threshold is 2.2V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.5V + \arg PMU_LVDT_4: voltage threshold is 2.6V + \arg PMU_LVDT_5: voltage threshold is 2.7V + \arg PMU_LVDT_6: voltage threshold is 2.8V + \arg PMU_LVDT_7: voltage threshold is 2.9V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo: + only one parameter can be selected which is shown as below: + \arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + static uint32_t reg_snap[ 4 ]; + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + reg_snap[ 0 ] = REG32( 0xE000E010U ); + reg_snap[ 1 ] = REG32( 0xE000E100U ); + reg_snap[ 2 ] = REG32( 0xE000E104U ); + reg_snap[ 3 ] = REG32( 0xE000E108U ); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF83DU; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFFFFFU; + + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + __SEV(); + __WFE(); + __WFE(); + } + + REG32( 0xE000E010U ) = reg_snap[ 0 ] ; + REG32( 0xE000E100U ) = reg_snap[ 1 ] ; + REG32( 0xE000E104U ) = reg_snap[ 2 ] ; + REG32( 0xE000E108U ) = reg_snap[ 3 ] ; + + /* reset sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief enable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief get flag state + \param[in] flag: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c new file mode 100644 index 0000000000..8eb52a4019 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c @@ -0,0 +1,1336 @@ +/*! + \file gd32f20x_rcu.c + \brief RCU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) +#define SEL_HXTAL ((uint16_t)1U) +#define SEL_PLL ((uint16_t)2U) + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0xFFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x3FFFFFFU) + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN ); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + + /* reset PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); + + /* reset CFG1 register */ + RCU_CFG1 = 0x00000000U; + + /* reset INT register */ + RCU_INT = 0x00FF0000U; + + /* reset CFG2 register */ + RCU_CFG2 = 0x00000000U; + + /* reset PLLTCTL register */ + RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); + + /* reset PLLTINT register */ + RCU_PLLTINT = 0x00400000U; + + /* Reset PLLTCFG register */ + RCU_PLLTCFG = 0x20003010U; +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock + \arg RCU_ENETTX: ENETTX clock + \arg RCU_ENETRX: ENETRX clock + \arg RCU_USBFS: USBFS clock + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2,5): USART clock + \arg RCU_UARTx (x=3,4,6,7): UART clock + \arg RCU_I2Cx (x=0,1,2): I2C clock + \arg RCU_CANx (x=0,1): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2): ADC clock + \arg RCU_SDIO: SDIO clock + \arg RCU_BKPI: BKP interface clock + \arg RCU_TLI: TLI clock + \arg RCU_DCI: DCI clock + \arg RCU_CAU: CAU clock + \arg RCU_HAU: HAU clock + \arg RCU_TRNG: TRNG clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock + \arg RCU_ENETTX: ENETTX clock + \arg RCU_ENETRX: ENETRX clock + \arg RCU_USBFS: USBFS clock + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2,5): USART clock + \arg RCU_UARTx (x=3,4,6,7): UART clock + \arg RCU_I2Cx (x=0,1,2): I2C clock + \arg RCU_CANx (x=0,1): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2): ADC clock + \arg RCU_SDIO: SDIO clock + \arg RCU_BKPI: BKP interface clock + \arg RCU_TLI: TLI clock + \arg RCU_DCI: DCI clock + \arg RCU_CAU: CAU clock + \arg RCU_HAU: HAU clock + \arg RCU_TRNG: TRNG clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET + \arg RCU_USBFSRST: reset USBFS + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2,5): reset USART + \arg RCU_UARTxRST (x=3,4,6,7): reset UART + \arg RCU_I2CxRST (x=0,1,2): reset I2C + \arg RCU_CANxRST (x=0,1): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2): reset ADC + \arg RCU_BKPIRST: reset BKPI + \arg RCU_TLIRST: reset TLI + \arg RCU_DCIRST: reset DCI + \arg RCU_CAURST: reset CAU + \arg RCU_HAURST: reset HAU + \arg RCU_TRNGRST: reset TRNG + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET + \arg RCU_USBFSRST: reset USBFS + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2,5): reset USART + \arg RCU_UARTxRST (x=3,4,6,7): reset UART + \arg RCU_I2CxRST (x=0,1,2): reset I2C + \arg RCU_CANxRST (x=0,1): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2): reset ADC + \arg RCU_BKPIRST: reset BKPI + \arg RCU_TLIRST: reset TLI + \arg RCU_DCIRST: reset DCI + \arg RCU_CAURST: reset CAU + \arg RCU_HAURST: reset HAU + \arg RCU_TRNGRST: reset TRNG + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source and divider + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL selected + \param[in] ckout0_div: CK_OUT0 divider + \arg RCU_CKOUT0_DIVx(x=1..64): CK_OUT0 is divided by x + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* set the CKOUT0SEL according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); + + reg = RCU_CFG2; + + /* set the CKOUT0DIV according to ckout0_div */ + reg &= ~RCU_CFG2_CKOUT0DIV; + RCU_CFG2 = (reg | ckout0_div); +} + +/*! + \brief configure the CK_OUT1 clock source and divider + \param[in] ckout1_src: CK_OUT1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT1SRC_NONE: no clock selected + \arg RCU_CKOUT1SRC_CKSYS: system clock selected + \arg RCU_CKOUT1SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT1SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT1SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT1SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT1SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT1SRC_EXT1: EXT1 selected + \arg RCU_CKOUT1SRC_CKPLL2: PLL selected + \param[in] ckout1_div: CK_OUT1 divider + \arg RCU_CKOUT1_DIVx(x=1..64): CK_OUT1 is divided by x + \param[out] none + \retval none +*/ +void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div) +{ + uint32_t reg; + + reg = RCU_CFG2; + /* set the CKOUT1SEL and CKOUT1DIV according to ckout1_src and ckout1_div */ + reg &= ~(RCU_CFG2_CKOUT1SEL | RCU_CFG2_CKOUT1DIV); + RCU_CFG2 = (reg | ckout1_src | ckout1_div); + +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + \arg RCU_PLL_MULx (x = 2..14,16..32,6.5) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0 = 0U; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << 14); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; +} + +/*! + \brief configure the USBFS/TRNG prescaler factor + \param[in] usbfs_trng_psc: USBFS/TRNG prescaler factor + \arg RCU_CKUSB_CKPLL_DIV1_5: USBFS/TRNG prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBFS/TRNG prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBFS/TRNG prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBFS/TRNG prescaler select CK_PLL/2 + \param[out] none + \retval none +*/ +void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* configure the USBFS/TRNG prescaler factor */ + reg &= ~RCU_CFG0_USBFSPSC; + RCU_CFG0 = (reg | usbfs_trng_psc); +} + + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2 x 2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2 x 2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag + \arg RCU_FLAG_PLLTSTB: PLLT stabilization flag + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization and ckm interrupt flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \arg RCU_INT_FLAG_PLLTSTB: PLLT stabilization interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \arg RCU_INT_FLAG_PLLTSTB_CLR: PLLT stabilization interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) +{ + RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + Only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief configure the LXTAL drive capability + \param[in] lxtal_dricap: drive capability of LXTAL + only one parameter can be selected which is shown as below: + \arg RCU_LXTAL_LOWDRI: lower driving capability + \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability + \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability + \arg RCU_LXTAL_HIGHDRI: higher driving capability + \param[out] none + \retval none +*/ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) +{ + uint32_t reg; + + reg = RCU_BDCTL; + + /* reset the LXTALDRI bits and set according to lxtal_dricap */ + reg &= ~RCU_BDCTL_LXTALDRI; + RCU_BDCTL = (reg | lxtal_dricap); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \arg RCU_PLLT_CK: TLI phase locked loop + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; + + /* wait PLLT stable */ + case RCU_PLLT_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLTSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLTSTB)){ + reval = SUCCESS; + } + break; + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \arg RCU_PLLT_CK: TLI phase locked loop + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \arg RCU_PLLT_CK: TLI phase locked loop + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: + case RCU_PLL1_CK: + case RCU_PLL2_CK: + case RCU_PLLT_CK: + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: + case RCU_PLL1_CK: + case RCU_PLL2_CK: + case RCU_PLLT_CK: + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V + \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp; + uint32_t predv0, predv1, pll1mf; + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src/predv1)*pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(13U == pllmf){ + /* PLL source clock multiply by 6.5 */ + cksys_freq = ck_src*6U + ck_src/2U; + }else{ + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + cksys_freq = ck_src*pllmf; + } + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} + +/*! + \brief configure the PLLT clock selection + \param[in] pllt_src: PLLT clock source selection + \arg RCU_PLLTSRC_IRC8M: IRC8M selected as source clock of PLLT + \arg RCU_PLLTSRC_HXTAL: HXTAL selected as source clock of PLLT + \param[out] none + \retval none +*/ +void rcu_pllt_config(uint32_t pllt_src) +{ + uint32_t reg = 0U; + + reg = RCU_PLLTCFG; + + /* reset the PLLT clock source bit PLLTSEL */ + reg &= ~RCU_PLLTCFG_PLLTSEL; + + RCU_PLLTCFG = (reg | pllt_src); +} + +/*! + \brief configure the PLLT clock multiplication and division factors + \param[in] pllt_psc: the PLLT VCO input clock division factor + \arg this parameter should be selected between 2 and 63. And this parameter should + be selected correctly to ensure that the VCO input frequency ranges from 1 to 2 MHz + \param[in] pllt_mul: he PLLT VCO output clock multiplication factor + \arg this parameter should be selected between 49 and 432 + \param[in] ppltr_psc: the PLLTR division factor + \arg this parameter should be selected between 2 and 7 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppltr_psc) +{ + uint32_t reg = 0U; + + /* check the function parameter */ + if((pllt_psc < 2U) || (pllt_psc > 63U)){ + return ERROR; + }else{ + } + + if((pllt_mul < 49U) || (pllt_mul > 432U)){ + return ERROR; + }else{ + } + + if((ppltr_psc < 2U) || (ppltr_psc > 7U)){ + return ERROR; + }else{ + } + + reg = RCU_PLLTCFG; + + /* reset the PLLTRPSC bits, PLLTMF bits and PLLTPSC bits */ + reg &= ~(RCU_PLLTCFG_PLLTRPSC | RCU_PLLTCFG_PLLTMF | RCU_PLLTCFG_PLLTPSC); + + reg |= (PLLTCFG_PLLTPSC(pllt_psc) | PLLTCFG_PLLTMF(pllt_mul) | PLLTCFG_PLLTRPSC(ppltr_psc)); + + RCU_PLLTCFG = reg; + + return SUCCESS; +} + +/*! + \brief configure the TLI prescaler factor from PLLTR clock + \param[in] tli_psc: TLI prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKTLI_CKPLLTR_DIV2: TLI prescaler select CK_PLLTR/2 + \arg RCU_CKTLI_CKPLLTR_DIV4: TLI prescaler select CK_PLLTR/4 + \arg RCU_CKTLI_CKPLLTR_DIV8: TLI prescaler select CK_PLLTR/8 + \arg RCU_CKTLI_CKPLLTR_DIV16: TLI prescaler select CK_PLLTR/16 + \param[out] none + \retval none +*/ +void rcu_tli_clock_config(uint32_t tli_psc) +{ + uint32_t reg = 0U; + + reg = RCU_PLLTCFG; + + /* reset the TLIPSC bits */ + reg &= ~RCU_PLLTCFG_TLIPSC; + + RCU_PLLTCFG = (reg | tli_psc); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c new file mode 100644 index 0000000000..4f8ae6f7dc --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c @@ -0,0 +1,276 @@ +/*! + \file gd32f20x_rtc.c + \brief RTC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_rtc.h" + +/* RTC register high / low bits mask */ +#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */ +#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */ + +/* RTC register high bits offset */ +#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U) + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET); + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET); + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET); + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + + temp = RTC_CNTL; + temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); + return temp; +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + + temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET); + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief get RTC interrupt flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_interrupt_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC interrupt flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval none +*/ +void rtc_interrupt_flag_clear(uint32_t flag) +{ + /* clear RTC interrupt flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c new file mode 100644 index 0000000000..c329af94d0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c @@ -0,0 +1,817 @@ +/*! + \file gd32f20x_sdio.c + \brief SDIO driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_sdio.h" + +#define DEFAULT_RESET_VALUE 0x00000000U + +/*! + \brief deinitialize the SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_deinit(void) +{ + SDIO_PWRCTL = DEFAULT_RESET_VALUE; + SDIO_CLKCTL = DEFAULT_RESET_VALUE; + SDIO_CMDAGMT = DEFAULT_RESET_VALUE; + SDIO_CMDCTL = DEFAULT_RESET_VALUE; + SDIO_DATATO = DEFAULT_RESET_VALUE; + SDIO_DATALEN = DEFAULT_RESET_VALUE; + SDIO_DATACTL = DEFAULT_RESET_VALUE; + SDIO_INTC = DEFAULT_RESET_VALUE; + SDIO_INTEN = DEFAULT_RESET_VALUE; +} + +/*! + \brief configure the SDIO clock + \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: + \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK + \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK + \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass + \arg SDIO_CLOCKBYPASS_DISABLE: no bypass + \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle + \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on + \param[in] clock_division: clock division, less than 512 + \param[out] none + \retval none +*/ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division) +{ + uint32_t clock_config = 0U; + clock_config = SDIO_CLKCTL; + /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ + clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV8 | SDIO_CLKCTL_DIV); + /* if the clock division is greater or equal to 256, set the DIV[8] */ + if(clock_division >= 256U){ + clock_config |= SDIO_CLKCTL_DIV8; + clock_division -= 256U; + } + /* configure the SDIO_CLKCTL according to the parameters */ + clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division); + SDIO_CLKCTL = clock_config; +} + +/*! + \brief enable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief disable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief set different SDIO card bus mode + \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: + \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode + \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode + \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode + \param[out] none + \retval none +*/ +void sdio_bus_mode_set(uint32_t bus_mode) +{ + /* reset the SDIO card bus mode bits and set according to bus_mode */ + SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE; + SDIO_CLKCTL |= bus_mode; +} + +/*! + \brief set the SDIO power state + \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off + \param[out] none + \retval none +*/ +void sdio_power_state_set(uint32_t power_state) +{ + SDIO_PWRCTL = power_state; +} + +/*! + \brief get the SDIO power state + \param[in] none + \param[out] none + \retval SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off +*/ +uint32_t sdio_power_state_get(void) +{ + return SDIO_PWRCTL; +} + +/*! + \brief enable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN; +} + +/*! + \brief disable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN; +} + +/*! + \brief configure the command and response + \param[in] cmd_index: command index, refer to the related specifications + \param[in] cmd_argument: command argument, refer to the related specifications + \param[in] response_type: response type + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSETYPE_NO: no response + \arg SDIO_RESPONSETYPE_SHORT: short response + \arg SDIO_RESPONSETYPE_LONG: long response + \param[out] none + \retval none +*/ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) +{ + uint32_t cmd_config = 0U; + /* reset the command index, command argument and response type */ + SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; + SDIO_CMDAGMT = cmd_argument; + cmd_config = SDIO_CMDCTL; + cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP); + /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */ + cmd_config |= (cmd_index | response_type); + SDIO_CMDCTL = cmd_config; +} + +/*! + \brief set the command state machine wait type + \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: + \arg SDIO_WAITTYPE_NO: not wait interrupt + \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt + \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer + \param[out] none + \retval none +*/ +void sdio_wait_type_set(uint32_t wait_type) +{ + /* reset INTWAIT and WAITDEND */ + SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND); + /* set the wait type according to wait_type */ + SDIO_CMDCTL |= wait_type; +} + +/*! + \brief enable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN; +} + +/*! + \brief disable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; +} + +/*! + \brief get the last response command index + \param[in] none + \param[out] none + \retval last response command index +*/ +uint8_t sdio_command_index_get(void) +{ + return (uint8_t)SDIO_RSPCMDIDX; +} + +/*! + \brief get the response for the last received command + \param[in] responsex: SDIO response + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] + \arg SDIO_RESPONSE1: card response[95:64] + \arg SDIO_RESPONSE2: card response[63:32] + \arg SDIO_RESPONSE3: card response[31:1], plus bit 0 + \param[out] none + \retval response for the last received command +*/ +uint32_t sdio_response_get(uint32_t responsex) +{ + uint32_t resp_content = 0U; + switch(responsex){ + case SDIO_RESPONSE0: + resp_content = SDIO_RESP0; + break; + case SDIO_RESPONSE1: + resp_content = SDIO_RESP1; + break; + case SDIO_RESPONSE2: + resp_content = SDIO_RESP2; + break; + case SDIO_RESPONSE3: + resp_content = SDIO_RESP3; + break; + default: + break; + } + return resp_content; +} + +/*! + \brief configure the data timeout, data length and data block size + \param[in] data_timeout: data timeout period in card bus clock periods + \param[in] data_length: number of data bytes to be transferred + \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: + \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte + \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes + \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes + \arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes + \arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes + \arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes + \arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes + \arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes + \arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes + \arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes + \arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes + \arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes + \arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes + \arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes + \arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes + \param[out] none + \retval none +*/ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize) +{ + /* reset data timeout, data length and data block size */ + SDIO_DATATO &= ~SDIO_DATATO_DATATO; + SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN; + SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ; + /* configure the related parameters of data */ + SDIO_DATATO = data_timeout; + SDIO_DATALEN = data_length; + SDIO_DATACTL |= data_blocksize; +} + +/*! + \brief configure the data transfer mode and direction + \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSMODE_BLOCK: block transfer + \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer + \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSDIRECTION_TOCARD: write data to card + \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card + \param[out] none + \retval none +*/ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction) +{ + uint32_t data_trans = 0U; + /* reset the data transfer mode, transfer direction and set according to the parameters */ + data_trans = SDIO_DATACTL; + data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR); + data_trans |= (transfer_mode | transfer_direction); + SDIO_DATACTL = data_trans; +} + +/*! + \brief enable the DSM(data state machine) for data transfer + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DATAEN; +} + +/*! + \brief disable the DSM(data state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN; +} + +/*! + \brief write data(one word) to the transmit FIFO + \param[in] data: 32-bit data write to card + \param[out] none + \retval none +*/ +void sdio_data_write(uint32_t data) +{ + SDIO_FIFO = data; +} + +/*! + \brief read data(one word) from the receive FIFO + \param[in] none + \param[out] none + \retval received data +*/ +uint32_t sdio_data_read(void) +{ + return SDIO_FIFO; +} + +/*! + \brief get the number of remaining data bytes to be transferred to card + \param[in] none + \param[out] none + \retval number of remaining data bytes to be transferred +*/ +uint32_t sdio_data_counter_get(void) +{ + return SDIO_DATACNT; +} + +/*! + \brief get the number of words remaining to be written or read from FIFO + \param[in] none + \param[out] none + \retval remaining number of words +*/ +uint32_t sdio_fifo_counter_get(void) +{ + return SDIO_FIFOCNT; +} + +/*! + \brief enable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DMAEN; +} + +/*! + \brief disable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN; +} + +/*! + \brief enable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWEN; +} + +/*! + \brief disable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWEN; +} + +/*! + \brief enable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWSTOP; +} + +/*! + \brief disable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP; +} + +/*! + \brief set the read wait type(SD I/O only) + \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: + \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK + \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] + \param[out] none + \retval none +*/ +void sdio_readwait_type_set(uint32_t readwait_type) +{ + if(SDIO_READWAITTYPE_CLK == readwait_type){ + SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; + }else{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; + } +} + +/*! + \brief enable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_IOEN; +} + +/*! + \brief disable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_IOEN; +} + +/*! + \brief enable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief disable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief enable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN; +} + +/*! + \brief disable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN; +} + +/*! + \brief enable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_enable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN; +} + +/*! + \brief disable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_disable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN; +} + +/*! + \brief enable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief disable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief get the flags state of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_CMDRUN: command transmission in progress flag + \arg SDIO_FLAG_TXRUN: data transmission in progress flag + \arg SDIO_FLAG_RXRUN: data reception in progress flag + \arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO + \arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO + \arg SDIO_FLAG_TFF: transmit FIFO is full flag + \arg SDIO_FLAG_RFF: receive FIFO is full flag + \arg SDIO_FLAG_TFE: transmit FIFO is empty flag + \arg SDIO_FLAG_RFE: receive FIFO is empty flag + \arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag + \arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_flag_get(uint32_t flag) +{ + FlagStatus temp_flag = RESET; + if(RESET != (SDIO_STAT & flag)){ + temp_flag = SET; + } + return temp_flag; +} + +/*! + \brief clear the pending flags of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_flag_clear(uint32_t flag) +{ + SDIO_INTC = flag; +} + +/*! + \brief enable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_enable(uint32_t int_flag) +{ + SDIO_INTEN |= int_flag; +} + +/*! + \brief disable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_disable(uint32_t int_flag) +{ + SDIO_INTEN &= ~int_flag; +} + +/*! + \brief get the interrupt flags state of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state = 0U; + state = SDIO_STAT; + if(state & int_flag){ + state = SDIO_INTEN; + /* check whether the corresponding bit in SDIO_INTEN is set or not */ + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear the interrupt pending flags of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_interrupt_flag_clear(uint32_t int_flag) +{ + SDIO_INTC = int_flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c new file mode 100644 index 0000000000..93cea07bf9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c @@ -0,0 +1,782 @@ +/*! + \file gd32f20x_spi.c + \brief SPI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_spi.h" + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */ + +/* default value and offset */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */ +#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ +#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with the default values + \param[in] spi_struct: SPI parameter stuct + \param[out] none + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct* spi_struct) +{ + /* set the SPI struct with the default values */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl) +{ + uint32_t reg = 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)mode; + /* select I2S standard */ + reg |= (uint32_t)standard; + /* select I2S polarity */ + reg |= (uint32_t)ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + + /* get the I2S clock source */ + if(SPI1 == ((uint32_t)spi_periph)){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET); + + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 14 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); + /* calculate I2S clock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* configure SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \param[out] none + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly) +{ + /* enable SPI CRC */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} + +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if((0U != reg1) && (0U != reg2)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + only one parameter can be selected which is shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(RESET != (SPI_STAT(spi_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} + +/*! + \brief enable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD; +} + +/*! + \brief disable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD); +} + +/*! + \brief enable quad wire SPI write + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_write_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD); +} + +/*! + \brief enable quad wire SPI read + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_read_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD; +} + +/*! + \brief enable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_io23_output_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV; +} + + /*! + \brief disable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_io23_output_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c new file mode 100644 index 0000000000..cb160dad57 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c @@ -0,0 +1,2000 @@ +/*! + \file gd32f20x_timer.c + \brief TIMER driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_timer.h" +/* TIMER init parameter mask */ +#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ +#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ +#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ + +/*! + \brief deinit a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + case TIMER7: + /* reset TIMER7 */ + rcu_periph_reset_enable(RCU_TIMER7RST); + rcu_periph_reset_disable(RCU_TIMER7RST); + break; + case TIMER8: + /* reset TIMER8 */ + rcu_periph_reset_enable(RCU_TIMER8RST); + rcu_periph_reset_disable(RCU_TIMER8RST); + break; + case TIMER9: + /* reset TIMER9 */ + rcu_periph_reset_enable(RCU_TIMER9RST); + rcu_periph_reset_disable(RCU_TIMER9RST); + break; + case TIMER10: + /* reset TIMER10 */ + rcu_periph_reset_enable(RCU_TIMER10RST); + rcu_periph_reset_disable(RCU_TIMER10RST); + break; + case TIMER11: + /* reset TIMER11 */ + rcu_periph_reset_enable(RCU_TIMER11RST); + rcu_periph_reset_disable(RCU_TIMER11RST); + break; + case TIMER12: + /* reset TIMER12 */ + rcu_periph_reset_enable(RCU_TIMER12RST); + rcu_periph_reset_disable(RCU_TIMER12RST); + break; + case TIMER13: + /* reset TIMER13 */ + rcu_periph_reset_enable(RCU_TIMER13RST); + rcu_periph_reset_disable(RCU_TIMER13RST); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock,0~65535 + alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP,TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN + period: counter auto reload value,0~65535 + clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) || + (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || + (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)){ + TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); + } + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] prescaler: prescaler value + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] repetition: the counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] autoreload: the counter auto-reload value + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] counter: the counter value + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..8,11) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow, + or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: TIMERx(x=0,1,2,5,14,15,16) + \param[in] dma: timer DMA source enable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: timer DMA source disable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA disable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request disable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA disable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: please refer to the following parameters + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: please refer to the following parameters + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_BRKG: break event generation, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) | + ((uint32_t)(breakpara->ideloffstate)) | + ((uint32_t)(breakpara->deadtime)) | + ((uint32_t)(breakpara->breakpolarity)) | + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode)) | + ((uint32_t)(breakpara->breakstate))) ; +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief enable or disable TIMER primary output function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 4U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 2U); + } + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 8U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 4U); + } + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 12U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 6U); + } + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM0 mode + \arg TIMER_OC_MODE_PWM1: PWM1 mode + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] pulse: channel output pulse value + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \arg TIMER_CH_3: TIMER channel3 + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING, + TIMER_IC_POLARITY_BOTH_EDGE(only for TIMER1~TIMER8) + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI, + TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, + TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,channel,(uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + case TIMER_CH_0: + /* read TIMER channel 0 capture compare register value */ + count_value = TIMER_CH0CV(timer_periph); + break; + case TIMER_CH_1: + /* read TIMER channel 1 capture compare register value */ + count_value = TIMER_CH1CV(timer_periph); + break; + case TIMER_CH_2: + /* read TIMER channel 2 capture compare register value */ + count_value = TIMER_CH2CV(timer_periph); + break; + case TIMER_CH_3: + /* read TIMER channel 3 capture compare register value */ + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \param[in] icpwm:TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity)<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection)<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: please refer to the following parameters + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channel 0 as trigger output TRGO(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4,7)) + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) +{ + /* configure the quadrature decoder mode */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + /* configure input capture selection */ + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + /* configure channel input capture polarity */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph,intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph, extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt source disable + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c new file mode 100644 index 0000000000..1e653dbc99 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c @@ -0,0 +1,481 @@ +/*! + \file gd32f20x_tli.c + \brief TLI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_tli.h" + +/*! + \brief deinitialize TLI registers + \param[in] none + \param[out] none + \retval none +*/ +void tli_deinit(void) +{ + rcu_periph_reset_enable(RCU_TLIRST); + rcu_periph_reset_disable(RCU_TLIRST); +} + +/*! + \brief initialize TLI display timing parameters + \param[in] tli_struct: the data needed to initialize tli + synpsz_vpsz: size of the vertical synchronous pulse + synpsz_hpsz: size of the horizontal synchronous pulse + backpsz_vbpsz: size of the vertical back porch plus synchronous pulse + backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse + activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse + activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse + totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous + totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous + backcolor_red: background value red + backcolor_green: background value green + backcolor_blue: background value blue + signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGHT + signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGHT + signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGHT + signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI + \param[out] none + \retval none +*/ +void tli_init(tli_parameter_struct *tli_struct) +{ + /* synchronous pulse size configuration */ + TLI_SPSZ &= ~(TLI_SPSZ_VPSZ|TLI_SPSZ_HPSZ); + TLI_SPSZ = (tli_struct->synpsz_vpsz|(tli_struct->synpsz_hpsz<<16U)); + /* back-porch size configuration */ + TLI_BPSZ &= ~(TLI_BPSZ_VBPSZ|TLI_BPSZ_HBPSZ); + TLI_BPSZ = (tli_struct->backpsz_vbpsz|(tli_struct->backpsz_hbpsz<<16U)); + /* active size configuration */ + TLI_ASZ &= ~(TLI_ASZ_VASZ|TLI_ASZ_HASZ); + TLI_ASZ = (tli_struct->activesz_vasz|(tli_struct->activesz_hasz<<16U)); + /* total size configuration */ + TLI_TSZ &= ~(TLI_TSZ_VTSZ|TLI_TSZ_HTSZ); + TLI_TSZ = (tli_struct->totalsz_vtsz|(tli_struct->totalsz_htsz<<16U)); + /* background color configuration */ + TLI_BGC &= ~(TLI_BGC_BVB|(TLI_BGC_BVG)|(TLI_BGC_BVR)); + TLI_BGC = (tli_struct->backcolor_blue|(tli_struct->backcolor_green<<8U)|(tli_struct->backcolor_red<<16U)); + TLI_CTL &= ~(TLI_CTL_HPPS|TLI_CTL_VPPS|TLI_CTL_DEPS|TLI_CTL_CLKPS); + TLI_CTL |= (tli_struct->signalpolarity_hs|tli_struct->signalpolarity_vs|\ + tli_struct->signalpolarity_de|tli_struct->signalpolarity_pixelck); +} + +/*! + \brief configure TLI dither function + \param[in] ditherstat + \arg TLI_DITHER_ENABLE + \arg TLI_DITHER_DISABLE + \param[out] none + \retval none +*/ +void tli_dither_config(uint8_t ditherstat) +{ + if(TLI_DITHER_ENABLE == ditherstat){ + TLI_CTL |= TLI_CTL_DFEN; + }else{ + TLI_CTL &= ~(TLI_CTL_DFEN); + } +} + +/*! + \brief TLI enable + \param[in] none + \param[out] none + \retval none +*/ +void tli_enable(void) +{ + TLI_CTL |= TLI_CTL_TLIEN; +} + +/*! + \brief TLI disable + \param[in] none + \param[out] none + \retval none +*/ +void tli_disable(void) +{ + TLI_CTL &= ~(TLI_CTL_TLIEN); +} + +/*! + \brief configure TLI reload mode + \param[in] reloadmode + \arg TLI_FRAME_BLANK_RELOAD_EN + \arg TLI_REQUEST_RELOAD_EN + \param[out] none + \retval none +*/ +void tli_reload_config(uint8_t reloadmode) +{ + if(TLI_FRAME_BLANK_RELOAD_EN == reloadmode){ + TLI_RL |= TLI_RL_FBR; + }else{ + TLI_RL |= TLI_RL_RQR; + } +} + +/*! + \brief set line mark value + \param[in] linenum: line number + \param[out] none + \retval none +*/ +void tli_line_mark_set(uint32_t linenum) +{ + TLI_LM &= ~(TLI_LM_LM); + TLI_LM = linenum; +} + +/*! + \brief get current displayed position + \param[in] none + \param[out] none + \retval none +*/ +uint32_t tli_current_pos_get(void) +{ + return TLI_CPPOS; +} + +/*! + \brief TLI layer enable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_layer_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LEN; +} + +/*! + \brief TLI layer disable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_layer_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN); +} + +/*! + \brief TLI layer color keying enable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN; +} + +/*! + \brief TLI layer color keying disable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN); +} + +/*! + \brief TLI layer LUT enable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN; +} + +/*! + \brief TLI layer LUT disable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN); +} + +/*! + \brief TLI layer initialize + \param[in] layerx: LAYERx(x=0,1) + \param[in] layer_struct: TLI Layer parameter struct + layer_window_rightpos: window right position + layer_window_leftpos: window left position + layer_window_bottompos: window bottom position + layer_window_toppos: window top position + layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565, + LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8, + LAYER_PPF_AL44,LAYER_PPF_AL88 + layer_sa: specified alpha + layer_default_alpha: the default color alpha + layer_default_red: the default color red + layer_default_green: the default color green + layer_default_blue: the default color blue + layer_acf1: LAYER_ACF1_SA,LAYER_ACF1_PASA + layer_acf2: LAYER_ACF2_SA,LAYER_ACF2_PASA + layer_frame_bufaddr: frame buffer base address + layer_frame_buf_stride_offset: frame buffer stride offset + layer_frame_line_length: frame line length + layer_frame_total_line_number: frame total line number + \param[out] none + \retval none +*/ +void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) +{ + /* configure layer window horizontal position */ + TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); + TLI_LxHPOS(layerx) = (layer_struct->layer_window_leftpos | (layer_struct->layer_window_rightpos<<16U)); + /* configure layer window vertical position */ + TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); + TLI_LxVPOS(layerx) = (layer_struct->layer_window_toppos |(layer_struct->layer_window_bottompos<<16U)); + /* configure layer packeted pixel format */ + TLI_LxPPF(layerx) &= ~(TLI_LxPPF_PPF); + TLI_LxPPF(layerx) = layer_struct->layer_ppf; + /* configure layer specified alpha */ + TLI_LxSA(layerx) &= ~(TLI_LxSA_SA); + TLI_LxSA(layerx) = layer_struct->layer_sa; + /* configure layer default color */ + TLI_LxDC(layerx) &= ~(TLI_LxDC_DCB|(TLI_LxDC_DCG)|(TLI_LxDC_DCR)|(TLI_LxDC_DCA)); + TLI_LxDC(layerx) = (layer_struct->layer_default_blue |(layer_struct->layer_default_green<<8U) + |(layer_struct->layer_default_red<<16U) + |(layer_struct->layer_default_alpha<<24U)); + + /* configure layer alpha calculation factors */ + TLI_LxBLEND(layerx) &= ~(TLI_LxBLEND_ACF2|(TLI_LxBLEND_ACF1)); + TLI_LxBLEND(layerx) = ((layer_struct->layer_acf2)|(layer_struct->layer_acf1)); + /* configure layer frame buffer base address */ + TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); + TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); + /* configure layer frame line length */ + TLI_LxFLLEN(layerx) &= ~(TLI_LxFLLEN_FLL|(TLI_LxFLLEN_STDOFF)); + TLI_LxFLLEN(layerx) = (layer_struct->layer_frame_line_length|(layer_struct->layer_frame_buf_stride_offset<<16U)); + /* configure layer frame buffer base address */ + TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); + TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); + /* configure layer frame total line number */ + TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN); + TLI_LxFTLN(layerx) = (layer_struct->layer_frame_total_line_number); +} + +/*! + \brief reconfigure window position + \param[in] layerx: LAYERx(x=0,1) + \param[in] offset_x: new horizontal offset + \param[in] offset_y: new vertical offset + \param[out] none + \retval none +*/ +void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y) +{ + /* configure window start position */ + uint32_t layer_ppf,line_length,line_num,hstart,vstart; + TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); + TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); + hstart = offset_x+(((TLI_BPSZ & TLI_BPSZ_HBPSZ)>>16U)+1U); + vstart = offset_y+((TLI_BPSZ & TLI_BPSZ_VBPSZ)+1U); + line_num = (TLI_LxFTLN(layerx) & TLI_LxFTLN_FTLN); + layer_ppf = (TLI_LxPPF(layerx) & TLI_LxPPF_PPF); + /* the bytes of a line equal TLI_LxFLLEN_FLL bits value minus 3 */ + switch(layer_ppf){ + case LAYER_PPF_ARGB8888: + /* each pixel includes 4bytes,when pixel format is ARGB8888 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/4U); + break; + case LAYER_PPF_RGB888: + /* each pixel includes 3bytes,when pixel format is RGB888 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/3U); + break; + case LAYER_PPF_RGB565: + case LAYER_PPF_ARGB1555: + case LAYER_PPF_ARGB4444: + case LAYER_PPF_AL88: + /* each pixel includes 2bytes,when pixel format is RGB565,ARG1555,ARGB4444 or AL88 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/2U); + break; + case LAYER_PPF_L8: + case LAYER_PPF_AL44: + /* each pixel includes 1byte,when pixel format is L8 or AL44 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)); + break; + default: + break; + } + /* reconfigure window position */ + TLI_LxHPOS(layerx) = (hstart|((hstart+line_length-1U)<<16U)); + TLI_LxVPOS(layerx) = (vstart|((vstart+line_num-1U)<<16U)); +} + +/*! + \brief TLI layer LUT initialize + \param[in] layerx: LAYERx(x=0,1) + \param[in] lut_struct: TLI layer LUT parameter struct + layer_table_addr: window right position + layer_lut_channel_red: window left position + layer_window_bottompos: window bottom position + layer_window_toppos: window top position + \param[out] none + \retval none +*/ +void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct) +{ + TLI_LxLUT(layerx) &= ~(TLI_LxLUT_TB|TLI_LxLUT_TG|TLI_LxLUT_TR|TLI_LxLUT_TADD); + TLI_LxLUT(layerx) = ((lut_struct->layer_lut_channel_blue)|(lut_struct->layer_lut_channel_green<<8) + |(lut_struct->layer_lut_channel_red<<16 + |(lut_struct->layer_table_addr<<24))); +} + +/*! + \brief TLI layer key initialize + \param[in] layerx: LAYERx(x=0,1) + \param[in] redkey: color key red + \param[in] greenkey: color key green + \param[in] bluekey: color key blue + \param[out] none + \retval none +*/ +void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey) +{ + TLI_LxCKEY(layerx) = ((bluekey)|(greenkey<<8U)|(redkey<<16U)); +} + +/*! + \brief get TLI flag or state + \param[in] flag: TLI flags or states + \arg TLI_FLAG_VDE: current VDE state + \arg TLI_FLAG_HDE: current HDE state + \arg TLI_FLAG_VS: current vs state + \arg TLI_FLAG_HS: current hs state + \arg TLI_FLAG_LM: line mark interrupt flag + \arg TLI_FLAG_FE: FIFO error interrupt flag + \arg TLI_FLAG_TE: transaction error interrupt flag + \arg TLI_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_flag_get(uint32_t flag) +{ + uint32_t stat; + if(flag >> 31){ + /* get flag status from TLI_INTF register */ + stat = TLI_INTF; + }else{ + /* get flag status from TLI_STAT register */ + stat = TLI_STAT; + } + if(flag & stat){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief enable TLI interrupt + \param[in] interrupt: TLI interrupt flags + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_enable(uint32_t interrupt) +{ + TLI_INTEN |= (interrupt); +} + +/*! + \brief disable TLI interrupt + \param[in] interrupt: TLI interrupt flags + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_disable(uint32_t interrupt) +{ + TLI_INTEN &= ~(interrupt); +} + +/*! + \brief get TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + \arg TLI_INT_FLAG_LM: line mark interrupt flag + \arg TLI_INT_FLAG_FE: FIFO error interrupt flag + \arg TLI_INT_FLAG_TE: transaction error interrupt flag + \arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state; + state = TLI_INTF; + if(state & int_flag){ + state = TLI_INTEN; + /* check whether the corresponding bit in TLI_INTEN is set or not */ + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + \arg TLI_INT_FLAG_LM: line mark interrupt flag + \arg TLI_INT_FLAG_FE: FIFO error interrupt flag + \arg TLI_INT_FLAG_TE: transaction error interrupt flag + \arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval none +*/ +void tli_interrupt_flag_clear(uint32_t int_flag) +{ + TLI_INTC |= (int_flag); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c new file mode 100644 index 0000000000..866b46053b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c @@ -0,0 +1,156 @@ +/*! + \file gd32f20x_trng.c + \brief TRNG driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_trng.h" + +/*! + \brief deinitialize the TRNG + \param[in] none + \param[out] none + \retval none +*/ +void trng_deinit(void) +{ + rcu_periph_reset_enable(RCU_TRNGRST); + rcu_periph_reset_disable(RCU_TRNGRST); +} + +/*! + \brief enable the TRNG interface + \param[in] none + \param[out] none + \retval none +*/ +void trng_enable(void) +{ + TRNG_CTL |= TRNG_CTL_TRNGEN; +} + +/*! + \brief disable the TRNG interface + \param[in] none + \param[out] none + \retval none +*/ +void trng_disable(void) +{ + TRNG_CTL &= ~TRNG_CTL_TRNGEN; +} + +/*! + \brief get the true random data + \param[in] none + \param[out] none + \retval the generated random data +*/ +uint32_t trng_get_true_random_data(void) +{ + return (TRNG_DATA); +} + +/*! + \brief get the trng status flags + \param[in] flag: trng status flag, refer to trng_flag_enum + only one parameter can be selected which is shown as below: + \arg TRNG_FLAG_DRDY: Random Data ready status + \arg TRNG_FLAG_CECS: Clock error current status + \arg TRNG_FLAG_SECS: Seed error current status + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus trng_flag_get(trng_flag_enum flag) +{ + if(RESET != (TRNG_STAT & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief enable the TRNG interrupt + \param[in] none + \param[out] none + \retval none +*/ +void trng_interrupt_enable(void) +{ + TRNG_CTL |= TRNG_CTL_IE; +} + +/*! + \brief disable the TRNG interrupt + \param[in] none + \param[out] none + \retval none +*/ +void trng_interrupt_disable(void) +{ + TRNG_CTL &= ~TRNG_CTL_IE; +} + +/*! + \brief get the trng interrupt flags + \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum + only one parameter can be selected which is shown as below: + \arg TRNG_INT_FLAG_CE: clock error interrupt flag + \arg TRNG_INT_FLAG_SE: Seed error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag) +{ + if(RESET != (TRNG_STAT & int_flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the trng interrupt flags + \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum + only one parameter can be selected which is shown as below: + \arg TRNG_INT_FLAG_CE: clock error interrupt flag + \arg TRNG_INT_FLAG_SE: Seed error interrupt flag + \param[out] none + \retval none +*/ +void trng_interrupt_flag_clear(trng_int_flag_enum int_flag) +{ + TRNG_STAT &= ~(uint32_t)int_flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c new file mode 100644 index 0000000000..d2767da8d2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c @@ -0,0 +1,923 @@ +/*! + \file gd32f20x_usart.c + \brief USART driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-04-11, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_usart.h" + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case USART5: + /* reset USART5 */ + rcu_periph_reset_enable(RCU_USART5RST); + rcu_periph_reset_disable(RCU_USART5RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + case UART6: + /* reset UART6 */ + rcu_periph_reset_enable(RCU_UART6RST); + rcu_periph_reset_disable(RCU_UART6RST); + break; + case UART7: + /* reset UART7 */ + rcu_periph_reset_enable(RCU_UART7RST); + rcu_periph_reset_disable(RCU_UART7RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART5: + /* get USART5 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART6: + /* get UART6 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART7: + /* get UART7 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* when oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & 0xfff0U; + fradiv = udiv & 0xfU; + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN Bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7)) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7)) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: enable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure receiver mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief data is transmitted/received with the LSB/MSB first + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] msbf: LSB/MSB + \arg USART_MSBF_LSB: LSB first + \arg USART_MSBF_MSB: MSB first + \param[out] none + \retval none +*/ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); + USART_CTL3(usart_periph) |= msbf; +} + +/*! + \brief configure USART inversion + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] invertpara: refer to enum USART_INVERT_CONFIG + \arg USART_DINV_ENABLE: data bit level inversion + \arg USART_DINV_DISABLE: data bit level not inversion + \arg USART_TXPIN_ENABLE: TX pin level inversion + \arg USART_TXPIN_DISABLE: TX pin level not inversion + \arg USART_RXPIN_ENABLE: RX pin level inversion + \arg USART_RXPIN_DISABLE: RX pin level not inversion + \param[out] none + \retval none +*/ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) +{ + /* inverted or not the specified siginal */ + switch(invertpara){ + case USART_DINV_ENABLE: + USART_CTL3(usart_periph) |= USART_CTL3_DINV; + break; + case USART_TXPIN_ENABLE: + USART_CTL3(usart_periph) |= USART_CTL3_TINV; + break; + case USART_RXPIN_ENABLE: + USART_CTL3(usart_periph) |= USART_CTL3_RINV; + break; + case USART_DINV_DISABLE: + USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); + break; + case USART_TXPIN_DISABLE: + USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); + break; + case USART_RXPIN_DISABLE: + USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); + break; + default: + break; + } +} + +/*! + \brief enable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_enable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) |= USART_CTL3_RTEN; +} + +/*! + \brief disable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_disable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN); +} + +/*! + \brief set the receiver timeout threshold of USART + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] rtimeout: 0-0xFFFFFF + \param[out] none + \retval none +*/ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout) +{ + USART_RT(usart_periph) &= ~(USART_RT_RT); + USART_RT(usart_periph) |= rtimeout; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint16_t data) +{ + USART_DATA(usart_periph) = ((uint16_t)USART_DATA_DATA & data); +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] guat: guard time value + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((guat)<<8)); +} + +/*! + \brief enable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_SCEN; +} + +/*! + \brief disable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); +} + +/*! + \brief enable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_NKEN; +} + +/*! + \brief disable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); +} + +/*! + \brief configure smartcard auto-retry number + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] scrtnum: smartcard auto-retry number + \param[out] none + \retval none +*/ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM); + USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((scrtnum)<<1)); +} + +/*! + \brief configure block length in Smartcard T=1 reception + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] bl: block length + \param[out] none + \retval none +*/ +void usart_block_length_config(uint32_t usart_periph, uint32_t bl) +{ + USART_RT(usart_periph) &= ~(USART_RT_BL); + USART_RT(usart_periph) |= (USART_RT_BL & ((bl)<<24)); +} + +/*! + \brief enable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_irda_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_IREN; +} + +/*! + \brief disable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_irda_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); +} + +/*! + \brief configure the peripheral clock prescaler in USART IrDA low-power mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] psc: 0x00-0xFF + \param[out] none + \retval none +*/ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) +{ + USART_GP(usart_periph) &= ~(USART_GP_PSC); + USART_GP(usart_periph) |= psc; +} + +/*! + \brief configure IrDA low-power + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] irlp: IrDA low-power or normal + only one parameter can be selected which is shown as below: + \arg USART_IRLP_LOW: low-power + \arg USART_IRLP_NORMAL: normal + \param[out] none + \retval none +*/ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); + USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); +} + +/*! + \brief configure hardware flow control RTS + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] hardwareflow: enable or disable RTS + only one parameter can be selected which is shown as below: + \arg USART_RTS_ENABLE: enable RTS + \arg USART_RTS_DISABLE: disable RTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_RTSEN; + ctl |= rtsconfig; + /* configure RTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure hardware flow control CTS + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] hardwareflow: enable or disable CTS + only one parameter can be selected which is shown as below: + \arg USART_CTS_ENABLE: enable CTS + \arg USART_CTS_DISABLE: disable CTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_CTSEN; + ctl |= ctsconfig; + /* configure CTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA reception + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] dmacmd: enable or disable DMA for reception + only one parameter can be selected which is shown as below: + \arg USART_DENR_ENABLE: DMA enable for reception + \arg USART_DENR_DISABLE: DMA disable for reception + \param[out] none + \retval none +*/ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENR; + ctl |= dmacmd; + /* configure DMA reception */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA transmission + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] dmacmd: enable or disable DMA for transmission + only one parameter can be selected which is shown as below: + \arg USART_DENT_ENABLE: DMA enable for transmission + \arg USART_DENT_DISABLE: DMA disable for transmission + \param[out] none + \retval none +*/ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENT; + ctl |= dmacmd; + /* configure DMA transmission */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief get flag in STAT0/STAT1 register + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTS: CTS change flag + \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_TBE: transmit data buffer empty + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_IDLE: IDLE frame detected flag + \arg USART_FLAG_ORERR: overrun error + \arg USART_FLAG_NERR: noise error flag + \arg USART_FLAG_FERR: frame error flag + \arg USART_FLAG_PERR: parity error flag + \arg USART_FLAG_BSY: busy flag + \arg USART_FLAG_EB: end of block flag + \arg USART_FLAG_RT: receiver timeout flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) +{ + if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag in STAT0/STAT1 register + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTS: CTS change flag + \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_EB: end of block flag + \arg USART_FLAG_RT: receiver timeout flag + \param[out] none + \retval none +*/ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) +{ + USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); +} + +/*! + \brief enable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \arg USART_INT_RT: interrupt enable bit of receive timeout event + \arg USART_INT_EB: interrupt enable bit of end of block event + \param[out] none + \retval none +*/ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief disable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \arg USART_INT_RT: interrupt enable bit of receive timeout event + \arg USART_INT_EB: interrupt enable bit of end of block event + \param[out] none + \retval none +*/ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief get USART interrupt and flag status + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_PERR: parity error interrupt and flag + \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag + \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error + \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag + \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag + \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag + \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag + \param[out] none + \retval FlagStatus +*/ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U; + /* get the interrupt enable bit status */ + intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); + + if(flagstatus && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear USART interrupt flag in STAT0/STAT1 register + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] flag: USART interrupt flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag + \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag + \param[out] none + \retval none +*/ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag) +{ + USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c new file mode 100644 index 0000000000..b61152551f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c @@ -0,0 +1,149 @@ +/*! + \file gd32f20x_wwdgt.c + \brief WWDGT driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_wwdgt.h" + +/* write value to WWDGT_CTL_CNT bit field */ +#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) +/* write value to WWDGT_CFG_WIN bit field */ +#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/*! + \brief reset the window watchdog timer configuration + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_deinit(void) +{ + rcu_periph_reset_enable(RCU_WWDGTRST); + rcu_periph_reset_disable(RCU_WWDGTRST); +} + +/*! + \brief start the window watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_enable(void) +{ + WWDGT_CTL |= WWDGT_CTL_WDGTEN; +} + +/*! + \brief configure the window watchdog timer counter value + \param[in] counter_value: 0x00 - 0x7F + \param[out] none + \retval none +*/ +void wwdgt_counter_update(uint16_t counter_value) +{ + uint32_t reg = 0U; + + reg = (WWDGT_CTL & (~WWDGT_CTL_CNT)); + reg |= CTL_CNT(counter_value); + + WWDGT_CTL = reg; +} + +/*! + \brief configure counter value, window value, and prescaler divider value + \param[in] counter: 0x00 - 0x7F + \param[in] window: 0x00 - 0x7F + \param[in] prescaler: wwdgt prescaler value + only one parameter can be selected which is shown as below: + \arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1 + \arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2 + \arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4 + \arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8 + \param[out] none + \retval none +*/ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) +{ + uint32_t reg_cfg = 0U, reg_ctl = 0U; + + /* clear WIN and PSC bits, clear CNT bit */ + reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC))); + reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT)); + + /* configure WIN and PSC bits, configure CNT bit */ + reg_cfg |= CFG_WIN(window); + reg_cfg |= prescaler; + reg_ctl |= CTL_CNT(counter); + + WWDGT_CTL = reg_ctl; + WWDGT_CFG = reg_cfg; +} + +/*! + \brief enable early wakeup interrupt of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_interrupt_enable(void) +{ + WWDGT_CFG |= WWDGT_CFG_EWIE; +} + +/*! + \brief check early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus wwdgt_flag_get(void) +{ + if(WWDGT_STAT & WWDGT_STAT_EWIF){ + return SET; + } + + return RESET; +} + +/*! + \brief clear early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_flag_clear(void) +{ + WWDGT_STAT &= (~WWDGT_STAT_EWIF); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..4e17823725 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..06c7dd63e8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..3d4422647c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,787 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* Volume Minimum Value */ +#define VOL_MAX 100U /* Volume Maximum Value */ +#define VOL_RES 1U /* Volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Tx endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Rx endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } +#endif /* USE_USB_AUDIO_SPEAKER */ + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..cff230f7c9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,228 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..e135a566f6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of CDC ACM driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..f77bcada34 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,525 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x + \version 2020-12-14, V3.0.2, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + + .req_proc = cdc_acm_req, + + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command Tx endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc = &udev->dev.transc_in[0]; + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc = &udev->dev.transc_out[0]; + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..1dfd377581 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..466bd36682 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..daeeb332cb --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,653 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); + +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static const usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in, +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to usb device instance + \param[out] none + \retval usb device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..ea4b155ac1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..826f4022ea --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..d6eff10ef1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..42c7495795 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,490 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED1); + } else { + gd_eval_led_off(LED1); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..4de0cae8c5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,390 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" + +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* Initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..30f8c3548e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,87 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send iap report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..82fb216f61 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,571 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t iap_data_in (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out, + .data_in = iap_data_in, +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send iap report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize Tx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the iap device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize iap endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the iap class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + + return USBD_OK; +} + +static uint8_t iap_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..bfaf8d7f27 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..bc59a7341a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..99ca1488d3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..a55e9a7a9d --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..e69a913285 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..efe159276f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initialize the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the Rx FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the Tx FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..d81a382cd4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,319 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +__ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC Tx endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC Rx endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..bc9fde2fd3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..39ddfd8f85 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,725 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + /* Evpd is set */ + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..0bc192d608 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..b023f4e0e8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to usb device instance + \param[in] req: device class-specific request + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..a3df6e8fbd --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions prototype + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..f01202a773 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..f8e2c8201a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..5daee80d2d --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to usb core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..68526e445e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..2c8c2823c2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,265 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..668d19cbea --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,163 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the Tx FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the Rx FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a Tx FIFO or all Tx FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire Rx FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..ce9ebdc9a8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,299 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< deinitialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device control in handler */ + uint8_t (*ctlx_out) (usb_dev *udev); /*!< device control out handler */ + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + usb_perp_dev dev; /*!< USB peripheral device */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..02bbbef2b4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,193 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; + usb_core_regs regs; + usb_host_drv host; +} usb_core_driver; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..fe84e310e3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,64 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..8421e8779f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,661 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + + +/* USB IN endpoint 0 transmit FIFO length register bits definitions */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< Transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< Packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< Embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..6988702f2f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..5a79112e9b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*port_enabled) (usbh_host *uhost); + uint8_t (*port_disabled) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..392d63f0a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,344 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to usb capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initializes the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the Tx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a Tx FIFO or all Tx FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for Tx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to usb core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for Rx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (0U == fifo) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..dae3b0e610 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,612 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 1 to 3's Tx FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all Tx FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire Rx FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the Tx FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure usb transaction to start OUT transfer + \param[in] udev: pointer to usb device + \param[in] transc: the usb OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..803a91bbab --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,452 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected usb host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_PFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all Tx FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to usb device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == udev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the Tx fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to usb device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..3ba5128bba --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,510 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); + +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +__IO uint8_t setupc_flag = 0U; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + if (0U != setupc_flag) { + setupc_flag ++; + + if (setupc_flag >= 3U) { + usbd_setup_transc (udev); + + setupc_flag = 0U; + } + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* Session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* Clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + if ((0U == ep_num) && (0U != setupc_flag)) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + + setupc_flag = 0U; + } + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + + setupc_flag = 1; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the Tx FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..8cecd56a4f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(udev->host.data); + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(udev->host.data); + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == udev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + udev->host.backup_xfercount[pp_num] = udev->host.pipe[pp_num].xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..341d20bb47 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + void (*machine)(usb_core_driver *udev, usbh_host *uhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..633687ddf5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void usr_keybrd_init (void); +/* process keyboard data */ +void usr_keybrd_process_data (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..83fcb37439 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void usr_mouse_init (void); +/* process mouse data */ +void usr_mouse_process_data (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..e77455d91b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,62 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..bca1fdf77c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..2c04da12ab --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,676 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *uhost); +static usbh_status usbh_hid_itf_init (usbh_host *uhost); +static usbh_status usbh_hid_class_req (usbh_host *uhost); +static usbh_status usbh_hid_handle (usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief de-initialize the host pipes used for the HID class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CHECK_CLASS == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check for available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(uhost->data, uhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to usb host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to usb host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to usb host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targetted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to usb host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..645bad1f63 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user init*/ + usr_keybrd_init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(udev, uhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(udev, uhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + usr_keybrd_process_data(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..09073ba971 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + usr_mouse_init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if(usbh_hid_mouse_decode(udev, uhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(udev, uhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + usr_mouse_process_data(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..35750e7db9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: Ok) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..42ccd19da6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *uhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction); +/* reset msc bot request structure */ +usbh_status usbh_msc_bot_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..48b103b652 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for msc process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..24bc0b3db4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..1877f35d2f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to usb host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (uhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(uhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to usb host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeture command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset msc bot transfer + \param[in] uhost: pointer to usb host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to usb host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..9f88e2db3e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,556 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0, sizeof(usbh_msc_handler)); + + uhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(uhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(uhost->data, msc_handler.ep_in); + + usbh_msc_bot_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief de-initialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for retreiving error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if ((uhost->control.timer - msc->timer) < 10000U) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..e710d86a1f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512U; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..1439698467 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implementing + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..d2d6269496 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,274 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* deinitialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..084c2879c2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..91d17f4266 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..677a9598a6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..2758d2a4b0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,650 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *uhost); +static uint8_t usbh_connect (usbh_host *uhost); +static uint8_t usbh_disconnect (usbh_host *uhost); +static uint8_t usbh_port_enabled (usbh_host *uhost); +static uint8_t usbh_port_disabled (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#ifdef USB_FS_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *udev); +static void usb_hwp_resume(usb_core_driver *udev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)uhost; + uhost->data = (void *)&usbh_core; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to usb host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief deinitialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, uhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + uhost->cur_state = HOST_DEV_ATTACHED; + + uhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#ifdef USB_FS_LOW_PWR_ENABLE + uhost->cur_state = HOST_SUSPENDED; +#else + uhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CHECK_CLASS; + } + } else { + uhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (uhost->class_num == 0U) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_FS_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + uhost->suspend_flag = 1; + usb_hwp_suspend(uhost->data); + uhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + + uhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* re-initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit(uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(&usbh_core); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *uhost) +{ + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[64]; + + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + + +#ifdef USB_FS_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..98c6c5ce8b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumberation driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to usb host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to usb host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to usb host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to usb host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to usb host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to usb host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to usb device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to usb configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to usb interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to usb endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by abstracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..a080d1eedf --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to usb core instance + \param[in] udev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(dev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to usb core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HC_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..a69cedfdcc --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,371 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to usb core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(uhost->data)- uhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..2d7f3a00c4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..ec00f44aed --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..1661f9351f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..d8e083b50c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..3aa557ee21 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..e567e8a59e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript new file mode 100644 index 0000000000..90cca69a13 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript @@ -0,0 +1,57 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/GD/GD32F20x/Source/system_gd32f20x.c +GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c +GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c +GD32F20x_standard_peripheral/Source/gd32f20x_exti.c +GD32F20x_standard_peripheral/Source/gd32f20x_misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_enet.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_dac.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c'] + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c'] + +path = [ + cwd + '/CMSIS/GD/GD32F20x/Include', + cwd + '/CMSIS', + cwd + '/GD32F20x_standard_peripheral/Include',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h new file mode 100644 index 0000000000..c9ba4bb0d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h @@ -0,0 +1,356 @@ +/*! + \file gd32f30x.h + \brief general definitions for GD32F30x + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_H +#define GD32F30X_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* define GD32F30x */ +#if !defined (GD32F30X_HD) && !defined (GD32F30X_XD) && !defined (GD32F30X_CL) + /* #define GD32F30X_HD */ + /* #define GD32F30X_XD */ + /* #define GD32F30X_CL */ +#endif /* define GD32F30x */ + +#if !defined (GD32F30X_HD) && !defined (GD32F30X_XD) && !defined (GD32F30X_CL) + #error "Please select the target GD32F30x device in gd32f30x.h file" +#endif /* undefine GD32F30x tip */ + +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32F30X_CL +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#else +#define HXTAL_VALUE ((uint32_t)8000000) /* !< from 4M to 32M *!< value of the external oscillator in Hz*/ +#endif /* HXTAL_VALUE */ +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined (HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 48MHz RC oscillator (IRC48M) in Hz */ +#if !defined (IRC48M_VALUE) +#define IRC48M_VALUE ((uint32_t)48000000) +#endif /* internal 48MHz RC oscillator value */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined (IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined (IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined (IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined (LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* GD32F30x firmware library version number V1.0 */ +#define __GD32F30x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __GD32F30x_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __GD32F30x_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __GD32F30x_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F30x_STDPERIPH_VERSION ((__GD32F30x_STDPERIPH_VERSION_MAIN << 24)\ + |(__GD32F30x_STDPERIPH_VERSION_SUB1 << 16)\ + |(__GD32F30x_STDPERIPH_VERSION_SUB2 << 8)\ + |(__GD32F30x_STDPERIPH_VERSION_RC)) + +/* configuration of the Cortex-M4 processor and core peripherals */ +#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1 /*!< GD32F30x provide MPU */ +#define __NVIC_PRIO_BITS 4 /*!< GD32F30x uses 4 bits for the priority levels */ +#define __Vendor_SysTickConfig 0 /*!< set to 1 if different sysTick config is used */ +#define __FPU_PRESENT 1 /*!< FPU present */ +/* define interrupt number */ +typedef enum IRQn +{ + /* Cortex-M4 processor exceptions numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 system tick interrupt */ + /* interruput numbers */ + WWDGT_IRQn = 0, /*!< window watchDog timer interrupt */ + LVD_IRQn = 1, /*!< LVD through EXTI line detect interrupt */ + TAMPER_IRQn = 2, /*!< tamper through EXTI line detect */ + RTC_IRQn = 3, /*!< RTC through EXTI line interrupt */ + FMC_IRQn = 4, /*!< FMC interrupt */ + RCU_CTC_IRQn = 5, /*!< RCU and CTC interrupt */ + EXTI0_IRQn = 6, /*!< EXTI line 0 interrupt */ + EXTI1_IRQn = 7, /*!< EXTI line 1 interrupt */ + EXTI2_IRQn = 8, /*!< EXTI line 2 interrupt */ + EXTI3_IRQn = 9, /*!< EXTI line 3 interrupt */ + EXTI4_IRQn = 10, /*!< EXTI line 4 interrupt */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel0 interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel1 interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel2 interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel3 interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel4 interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel5 interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel6 interrupt */ + ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 interrupt */ +#ifdef GD32F30X_HD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupt */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupt */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD Wakeup interrupt */ + TIMER7_BRK_IRQn = 43, /*!< TIMER7 break interrupt */ + TIMER7_UP_IRQn = 44, /*!< TIMER7 update interrupt */ + TIMER7_TRG_CMT_IRQn = 45, /*!< TIMER7 trigger and commutation interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global Interrupt */ +#endif /* GD32F30X_HD */ + +#ifdef GD32F30X_XD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupt */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupt */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupt */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupt */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global interrupt */ +#endif /* GD32F30X_XD */ + +#ifdef GD32F30X_CL + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupt */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupt */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupt */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupt */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_ALARM_IRQn = 41, /*!< RTC alarm interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupt */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupt */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 global interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel3 global interrupt */ + ENET_IRQn = 61, /*!< ENET global interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET Wakeup interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ +#endif /* GD32F30X_CL */ + +} IRQn_Type; + +/* includes */ +#include "core_cm4.h" +#include "system_gd32f30x.h" +#include + +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM0 base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB3_BUS_BASE ((uint32_t)0x60000000U) /*!< ahb3 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define USBD_BASE (APB1_BUS_BASE + 0x00005C00U) /*!< USBD base address */ +#define USBD_RAM_BASE (APB1_BUS_BASE + 0x00006000U) /*!< USBD RAM base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ +#define CTC_BASE (APB1_BUS_BASE + 0x0000C800U) /*!< CTC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ + +/* advanced high performance bus 1 memory map */ +#define SDIO_BASE (AHB1_BUS_BASE + 0x00000000U) /*!< SDIO base address */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define ENET_BASE (AHB1_BUS_BASE + 0x00010000U) /*!< ENET base address */ +#define USBFS_BASE (AHB1_BUS_BASE + 0x0FFE8000U) /*!< USBFS base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32f30x_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h new file mode 100644 index 0000000000..69e7366e38 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h @@ -0,0 +1,57 @@ +/*! + \file system_gd32f30x.h + \brief CMSIS Cortex-M4 Device Peripheral Access Layer Header File for + GD32F30x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32F30X_H +#define SYSTEM_GD32F30X_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit (void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32F30X_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s new file mode 100644 index 0000000000..b274d61156 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s @@ -0,0 +1,385 @@ +;/*! +; \file startup_gd32f30x_cl.s +; \brief start up file +; +; \version 2017-02-10, V1.0.0, firmware for GD32F30x +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2018-12-25, V2.0.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000400 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; 64:EXMC + DCD 0 ; Reserved + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler\ + PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler\ + PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_CTC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT CAN0_TX_IRQHandler [WEAK] + EXPORT CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBFS_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT ENET_IRQHandler [WEAK] + EXPORT ENET_WKUP_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_EWMC_IRQHandler [WEAK] + EXPORT USBFS_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_CTC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +CAN0_TX_IRQHandler +CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBFS_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +EXMC_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +ENET_IRQHandler +ENET_WKUP_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_EWMC_IRQHandler +USBFS_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s new file mode 100644 index 0000000000..cbc0764d63 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s @@ -0,0 +1,365 @@ +;/*! +; \file startup_gd32f30x_hd.s +; \brief start up file +; +; \version 2017-02-10, V1.0.0, firmware for GD32F30x +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2018-12-25, V2.0.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000400 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commutation + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler\ + PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler\ + PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_CTC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_IRQHandler [WEAK] + EXPORT TIMER7_UP_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_CTC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_IRQHandler +TIMER7_UP_IRQHandler +TIMER7_TRG_CMT_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s new file mode 100644 index 0000000000..4475675eca --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s @@ -0,0 +1,365 @@ +;/*! +; \file startup_gd32f30x_xd.s +; \brief start up file +; +; \version 2017-02-10, V1.0.0, firmware for GD32F30x +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2018-12-25, V2.0.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000400 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler\ + PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler\ + PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_CTC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_CTC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s new file mode 100644 index 0000000000..8db890e280 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s @@ -0,0 +1,271 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word 0 // 63:Reserved + .word EXMC_IRQHandler // 64:EXMC + .word 0 // 65:Reserved + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_IRQHandler // 75:DMA1 Channel3 + .word ENET_IRQHandler // 77:Ethernet + .word ENET_WKUP_IRQHandler // 78:Ethernet Wakeup through EXTI Line + .word CAN1_TX_IRQHandler // 79:CAN1 TX + .word CAN1_RX0_IRQHandler // 80:CAN1 RX0 + .word CAN1_RX1_IRQHandler // 81:CAN1 RX1 + .word CAN1_EWMC_IRQHandler // 82:CAN1 EWMC + .word USBFS_IRQHandler // 83:USBFS + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_IRQHandler + IRQ ENET_IRQHandler + IRQ ENET_WKUP_IRQHandler + IRQ CAN1_TX_IRQHandler + IRQ CAN1_RX0_IRQHandler + IRQ CAN1_RX1_IRQHandler + IRQ CAN1_EWMC_IRQHandler + IRQ USBFS_IRQHandlerBFS diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s new file mode 100644 index 0000000000..a65aa8ed0c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s new file mode 100644 index 0000000000..a65aa8ed0c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s new file mode 100644 index 0000000000..4e1fd63ef4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s @@ -0,0 +1,525 @@ +;/*! +; \file startup_gd32f30x_cl.s +; \brief start up file +; +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Vector Number 1,Reset Handler + + DCD NMI_Handler ; Vector Number 2,NMI Handler + DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler + DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler + DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler + DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; Vector Number 11,SVCall Handler + DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; Vector Number 14,PendSV Handler + DCD SysTick_Handler ; Vector Number 15,SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commucation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commucation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD 0 ; 63:Reserved + DCD EXMC_IRQHandler ; 64:EXMC + DCD 0 ; 65:Reserved + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_CTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_CTC_IRQHandler + B RCU_CTC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_TX_IRQHandler + B CAN0_TX_IRQHandler + + PUBWEAK CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX0_IRQHandler + B CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBFS_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_WKUP_IRQHandler + B USBFS_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK ENET_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_IRQHandler + B ENET_IRQHandler + + PUBWEAK ENET_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_WKUP_IRQHandler + B ENET_WKUP_IRQHandler + + PUBWEAK CAN1_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX0_IRQHandler + B CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_EWMC_IRQHandler + B CAN1_EWMC_IRQHandler + + PUBWEAK USBFS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_IRQHandler + B USBFS_IRQHandler + END \ No newline at end of file diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s new file mode 100644 index 0000000000..71b952f830 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s @@ -0,0 +1,487 @@ +;/*! +; \file startup_gd32f30x_hd.s +; \brief start up file +; +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Vector Number 1,Reset Handler + + DCD NMI_Handler ; Vector Number 2,NMI Handler + DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler + DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler + DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler + DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; Vector Number 11,SVCall Handler + DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; Vector Number 14,PendSV Handler + DCD SysTick_Handler ; Vector Number 15,SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commucation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commucation + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and channel4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_CTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_CTC_IRQHandler + B RCU_CTC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_IRQHandler + B TIMER7_BRK_IRQHandler + + PUBWEAK TIMER7_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_IRQHandler + B TIMER7_UP_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_IRQHandler + B TIMER7_TRG_CMT_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + END \ No newline at end of file diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s new file mode 100644 index 0000000000..1eb465900d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s @@ -0,0 +1,487 @@ +;/*! +; \file startup_gd32f30x_xd.s +; \brief start up file +; +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Vector Number 1,Reset Handler + + DCD NMI_Handler ; Vector Number 2,NMI Handler + DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler + DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler + DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler + DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; Vector Number 11,SVCall Handler + DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; Vector Number 14,PendSV Handler + DCD SysTick_Handler ; Vector Number 15,SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commucation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commucation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and channel4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_CTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_CTC_IRQHandler + B RCU_CTC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + END \ No newline at end of file diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c new file mode 100644 index 0000000000..65455622f0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c @@ -0,0 +1,996 @@ +/*! + \file system_gd32f30x.c + \brief CMSIS Cortex-M4 Device Peripheral Access Layer Source File for + GD32F30x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#include "gd32f30x.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) +//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) + +/* use HXTAL(XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ +//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) +#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U +#define RCU_MODIFY {volatile uint32_t i; \ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \ + for(i=0;i<20000;i++);} + +/* set the system clock frequency and declare the system clock configuration function */ +#ifdef __SYSTEM_CLOCK_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M; +static void system_clock_8m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M; +static void system_clock_120m_irc8m(void); + +#elif defined (__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL; +static void system_clock_120m_hxtal(void); +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit (void) +{ + /* FPU settings */ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ +#endif + /* reset the RCU clock configuration to the default reset state */ + /* Set IRC8MEN bit */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + RCU_MODIFY + + /* Reset CFG0 and CFG1 registers */ + RCU_CFG0 = 0x00000000U; + RCU_CFG1 = 0x00000000U; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* reset HXTALEN, CKMEN and PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x009f0000U; +#elif defined(GD32F30X_CL) + /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x00ff0000U; +#endif + + /* reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); +} +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#ifdef __SYSTEM_CLOCK_IRC8M + system_clock_8m_irc8m(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) + system_clock_120m_irc8m(); + +#elif defined (__SYSTEM_CLOCK_HXTAL) + system_clock_hxtal(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) + system_clock_120m_hxtal(); +#endif /* __SYSTEM_CLOCK_IRC8M */ +} + +#ifdef __SYSTEM_CLOCK_IRC8M +/*! + \brief configure the system clock to 8M by IRC8M + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_8m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select IRC8M as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; + + /* wait until IRC8M is selected as system clock */ + while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL12; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL18; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL27; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +/*! + \brief configure the system clock to 120M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL30; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_HXTAL) +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL12; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL12); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL18; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL27; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL27); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +/*! + \brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL30; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate(void) +{ + uint32_t sws; + uint32_t pllsel, pllpresel, predv0sel, pllmf, ck_src, idx, clk_exp; + /* exponent of AHB, APB1 and APB2 clock divider */ + const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +#ifdef GD32F30X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F30X_CL */ + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL_IRC48M == pllsel){ + /* PLL clock source is HXTAL or IRC48M */ + pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); + + if(RCU_PLLPRESRC_HXTAL == pllpresel){ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + }else{ + /* PLL clock source is IRC48 */ + ck_src = IRC48M_VALUE; + } + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE / 2U; + } +#elif defined(GD32F30X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F30X_HD and GD32F30X_XD */ + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE / 2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ + pllmf |= 0x20U; + } + + if( pllmf >= 15U){ + pllmf += 1U; + }else{ + pllmf += 2U; + } + if(pllmf > 61U){ + pllmf = 63U; + } + SystemCoreClock = ck_src * pllmf; + #ifdef GD32F30X_CL + if(15U == pllmf){ + SystemCoreClock = (ck_src * 6U) + (ck_src / 2U); + } + #endif /* GD32F30X_CL */ + break; + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + SystemCoreClock = SystemCoreClock >> clk_exp; +} diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4.h rename to bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4_simd.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4_simd.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4_simd.h rename to bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4_simd.h diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h new file mode 100644 index 0000000000..3c932e0d6e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h @@ -0,0 +1,616 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h new file mode 100644 index 0000000000..597e64df04 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h @@ -0,0 +1,618 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + uint32_t result; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + + __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); + return(op1); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint8_t result; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint16_t result; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint8_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h new file mode 100644 index 0000000000..7a778867dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h @@ -0,0 +1,403 @@ +/*! + \file gd32f30x_adc.h + \brief definitions for the ADC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_ADC_H +#define GD32F30X_ADC_H + +#include "gd32f30x.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define ADC2 (ADC_BASE + 0x1800U) +#endif + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ +#define ADC_OVSAMPCTL(adcx) REG32((adcx) + 0x80U) /*!< ADC oversampling control register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0,4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13,15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16,19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ +#define ADC_CTL0_DRES BITS(24,25) /*!< ADC data resolution */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17,19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger conversion mode for inserted channels */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0..1 */ +#define ADC_SAMPTX_SPTN BITS(0,2) /*!< channel x sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0,11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0,11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0,11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx */ +#define ADC_RSQX_RSQN BITS(0,4) /*!< x conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20,23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0,4) /*!< x conversion in regular sequence */ +#define ADC_ISQ_IL BITS(20,21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0,15) /*!< inserted data x */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0,15) /*!< regular data */ +#define ADC_RDATA_ADC1RDTR BITS(16,31) /*!< ADC1 regular channel data */ + +/* ADC_OVSAMPCTL */ +#define ADC_OVSAMPCTL_OVSEN BIT(0) /*!< oversampling enable */ +#define ADC_OVSAMPCTL_OVSR BITS(2,4) /*!< oversampling ratio */ +#define ADC_OVSAMPCTL_OVSS BITS(5,8) /*!< oversampling shift */ +#define ADC_OVSAMPCTL_TOVS BIT(9) /*!< triggered oversampling */ +#define ADC_OVSAMPCTL_DRES BITS(12,13) /*!< oversampling shift */ + + +/* constants definitions */ +/* ADC status flag */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< inserted channel end of conversion */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* ADC special function definitions */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* ADC synchronization mode */ +#define CTL0_SYNCM(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* ADC data alignment */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* ADC external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< timer 0 CC0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< timer 0 CC1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< timer 0 CC2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< timer 1 CC1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< timer 2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< timer 3 CC3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(6) /*!< timer 7 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_2_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ + +#define ADC2_EXTTRIG_REGULAR_T2_CH0 CTL1_ETSRC(0) /*!< timer 2 CC0 event select */ +#define ADC2_EXTTRIG_REGULAR_T1_CH2 CTL1_ETSRC(1) /*!< timer 1 CC2 event select */ +#define ADC2_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< timer 0 CC2 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_CH0 CTL1_ETSRC(3) /*!< timer 7 CC0 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(4) /*!< timer 7 TRGO event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< timer 4 CC0 event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< timer 4 CC2 event select */ + +/* ADC external trigger select for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< timer 0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< timer 0 CC3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< timer 1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< timer 1 CC0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< timer 2 CC3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< timer 3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(6) /*!< timer 7 CC3 event select */ +#define ADC0_1_2_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ + +#define ADC2_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< timer 0 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< timer 0 CC3 event select */ +#define ADC2_EXTTRIG_INSERTED_T3_CH2 CTL1_ETSIC(2) /*!< timer 3 CC2 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH1 CTL1_ETSIC(3) /*!< timer 7 CC1 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(4) /*!< timer 7 CC3 event select */ +#define ADC2_EXTTRIG_INSERTED_T4_TRGO CTL1_ETSIC(5) /*!< timer 4 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T4_CH3 CTL1_ETSIC(6) /*!< timer 4 CC3 event select */ + +/* ADC channel sample time */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* adc_ovsampctl register value */ +/* ADC resolution */ +#define OVSAMPCTL_DRES(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_OVSAMPCTL_DRES bit field */ +#define ADC_RESOLUTION_12B OVSAMPCTL_DRES(0) /*!< 12-bit ADC resolution */ +#define ADC_RESOLUTION_10B OVSAMPCTL_DRES(1) /*!< 10-bit ADC resolution */ +#define ADC_RESOLUTION_8B OVSAMPCTL_DRES(2) /*!< 8-bit ADC resolution */ +#define ADC_RESOLUTION_6B OVSAMPCTL_DRES(3) /*!< 6-bit ADC resolution */ + +/* oversampling shift */ +#define OVSAMPCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) /*!< write value to ADC_OVSAMPCTL_OVSS bit field */ +#define ADC_OVERSAMPLING_SHIFT_NONE OVSAMPCTL_OVSS(0) /*!< no oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_1B OVSAMPCTL_OVSS(1) /*!< 1-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_2B OVSAMPCTL_OVSS(2) /*!< 2-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_3B OVSAMPCTL_OVSS(3) /*!< 3-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_4B OVSAMPCTL_OVSS(4) /*!< 4-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_5B OVSAMPCTL_OVSS(5) /*!< 5-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_6B OVSAMPCTL_OVSS(6) /*!< 6-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_7B OVSAMPCTL_OVSS(7) /*!< 7-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_8B OVSAMPCTL_OVSS(8) /*!< 8-bit oversampling shift */ + +/* oversampling ratio */ +#define OVSAMPCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ADC_OVSAMPCTL_OVSR bit field */ +#define ADC_OVERSAMPLING_RATIO_MUL2 OVSAMPCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ +#define ADC_OVERSAMPLING_RATIO_MUL4 OVSAMPCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ +#define ADC_OVERSAMPLING_RATIO_MUL8 OVSAMPCTL_OVSR(2) /*!< oversampling ratio multiple 8 */ +#define ADC_OVERSAMPLING_RATIO_MUL16 OVSAMPCTL_OVSR(3) /*!< oversampling ratio multiple 16 */ +#define ADC_OVERSAMPLING_RATIO_MUL32 OVSAMPCTL_OVSR(4) /*!< oversampling ratio multiple 32 */ +#define ADC_OVERSAMPLING_RATIO_MUL64 OVSAMPCTL_OVSR(5) /*!< oversampling ratio multiple 64 */ +#define ADC_OVERSAMPLING_RATIO_MUL128 OVSAMPCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ +#define ADC_OVERSAMPLING_RATIO_MUL256 OVSAMPCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ + +/* triggered oversampling */ +#define ADC_OVERSAMPLING_ALL_CONVERT ((uint32_t)0x00000000U) /*!< all oversampled conversions for a channel are done consecutively after a trigger */ +#define ADC_OVERSAMPLING_ONE_CONVERT ADC_OVSAMPCTL_TOVS /*!< each oversampled conversion for a channel needs a trigger */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< adc regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< adc inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* function declarations */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* configure ADC resolution */ +void adc_resolution_config(uint32_t adc_periph , uint32_t resolution); +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length); + +/* configure the ADC mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment); +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset); +/* enable ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group); + +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag); +/* get the ADC interrupt bits */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt); +/* clear the ADC flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph , uint32_t adc_interrupt); + +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold); + +/* configure ADC oversample mode */ +void adc_oversample_mode_config(uint32_t adc_periph , uint32_t mode , uint16_t shift , uint8_t ratio); +/* enable ADC oversample mode */ +void adc_oversample_mode_enable(uint32_t adc_periph); +/* disable ADC oversample mode */ +void adc_oversample_mode_disable(uint32_t adc_periph); +#endif /* GD32F30X_ADC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h new file mode 100644 index 0000000000..31636783b3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h @@ -0,0 +1,244 @@ +/*! + \file gd32f30x_bkp.h + \brief definitions for the BKP + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_BKP_H +#define GD32F30X_BKP_H + +#include "gd32f30x.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL REG16((BKP) + 0x30U) /*!< tamper pin control register */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0,15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0,6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ +#define BKP_OCTL_CCOSEL BIT(14) /*!< RTC clock output selection */ +#define BKP_OCTL_CALDIR BIT(15) /*!< RTC clock calibration direction */ + +/* BKP_TPCTL */ +#define BKP_TPCTL_TPEN BIT(0) /*!< tamper detection enable */ +#define BKP_TPCTL_TPAL BIT(1) /*!< tamper pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER BIT(0) /*!< tamper event reset */ +#define BKP_TPCS_TIR BIT(1) /*!< tamper interrupt reset */ +#define BKP_TPCS_TPIE BIT(2) /*!< tamper interrupt enable */ +#define BKP_TPCS_TEF BIT(8) /*!< tamper event flag */ +#define BKP_TPCS_TIF BIT(9) /*!< tamper interrupt flag */ + +/* constants definitions */ +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* RTC clock output selection */ +#define RTC_CLOCK_DIV_64 ((uint16_t)0x0000U) /*!< RTC clock div 64 */ +#define RTC_CLOCK_DIV_1 ((uint16_t)0x4000U) /*!< RTC clock div 1 */ + +/* RTC clock calibration direction */ +#define RTC_CLOCK_SLOWED_DOWN ((uint16_t)0x0000U) /*!< RTC clock slow down */ +#define RTC_CLOCK_SPEED_UP ((uint16_t)0x8000U) /*!< RTC clock speed up */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER BKP_TPCS_TEF /*!< tamper event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER BKP_TPCS_TIF /*!< tamper interrupt flag */ + +/* BKP data register number */ +typedef enum +{ + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +}bkp_data_register_enum; + +/* function declarations */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_write_data(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_read_data(bkp_data_register_enum register_number); + +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* RTC output selection */ +void bkp_rtc_output_select(uint16_t outputsel); +/* RTC clock output selection */ +void bkp_rtc_clock_output_select(uint16_t clocksel); +/* RTC clock calibration direction */ +void bkp_rtc_clock_calibration_direction(uint16_t direction); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(void); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(void); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(uint16_t level); +/* enable tamper pin interrupt */ +void bkp_tamper_interrupt_enable(void); +/* disable tamper pin interrupt */ +void bkp_tamper_interrupt_disable(void); + +/* flag functions */ +/* get BKP flag state */ +FlagStatus bkp_flag_get(uint16_t flag); +/* clear BKP flag state */ +void bkp_flag_clear(uint16_t flag); +/* get BKP interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(uint16_t flag); +/* clear BKP interrupt flag state */ +void bkp_interrupt_flag_clear(uint16_t flag); + +#endif /* GD32F30X_BKP_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h new file mode 100644 index 0000000000..c3953d1293 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h @@ -0,0 +1,754 @@ +/*! + \file gd32f30x_can.h + \brief definitions for the CAN + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-11-27, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_CAN_H +#define GD32F30X_CAN_H + +#include "gd32f30x.h" + +/* CAN definitions */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ + +/* registers definitions */ +#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ + +/* CAN transmit mailbox bank */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ + +/* CAN filter bank */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ + +/* CAN receive fifo mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ + +/* bits definitions */ +/* CAN_CTL */ +#define CAN_CTL_IWMOD BIT(0) /*!< initial working mode */ +#define CAN_CTL_SLPWMOD BIT(1) /*!< sleep working mode */ +#define CAN_CTL_TFO BIT(2) /*!< transmit FIFO order */ +#define CAN_CTL_RFOD BIT(3) /*!< receive FIFO overwrite disable */ +#define CAN_CTL_ARD BIT(4) /*!< automatic retransmission disable */ +#define CAN_CTL_AWU BIT(5) /*!< automatic wakeup */ +#define CAN_CTL_ABOR BIT(6) /*!< automatic bus-off recovery */ +#define CAN_CTL_TTC BIT(7) /*!< time triggered communication */ +#define CAN_CTL_SWRST BIT(15) /*!< CAN software reset */ +#define CAN_CTL_DFZ BIT(16) /*!< CAN debug freeze */ + +/* CAN_STAT */ +#define CAN_STAT_IWS BIT(0) /*!< initial working state */ +#define CAN_STAT_SLPWS BIT(1) /*!< sleep working state */ +#define CAN_STAT_ERRIF BIT(2) /*!< error interrupt flag*/ +#define CAN_STAT_WUIF BIT(3) /*!< status change interrupt flag of wakeup from sleep working mode */ +#define CAN_STAT_SLPIF BIT(4) /*!< status change interrupt flag of sleep working mode entering */ +#define CAN_STAT_TS BIT(8) /*!< transmitting state */ +#define CAN_STAT_RS BIT(9) /*!< receiving state */ +#define CAN_STAT_LASTRX BIT(10) /*!< last sample value of rx pin */ +#define CAN_STAT_RXL BIT(11) /*!< CAN rx signal */ + +/* CAN_TSTAT */ +#define CAN_TSTAT_MTF0 BIT(0) /*!< mailbox0 transmit finished */ +#define CAN_TSTAT_MTFNERR0 BIT(1) /*!< mailbox0 transmit finished and no error */ +#define CAN_TSTAT_MAL0 BIT(2) /*!< mailbox0 arbitration lost */ +#define CAN_TSTAT_MTE0 BIT(3) /*!< mailbox0 transmit error */ +#define CAN_TSTAT_MST0 BIT(7) /*!< mailbox0 stop transmitting */ +#define CAN_TSTAT_MTF1 BIT(8) /*!< mailbox1 transmit finished */ +#define CAN_TSTAT_MTFNERR1 BIT(9) /*!< mailbox1 transmit finished and no error */ +#define CAN_TSTAT_MAL1 BIT(10) /*!< mailbox1 arbitration lost */ +#define CAN_TSTAT_MTE1 BIT(11) /*!< mailbox1 transmit error */ +#define CAN_TSTAT_MST1 BIT(15) /*!< mailbox1 stop transmitting */ +#define CAN_TSTAT_MTF2 BIT(16) /*!< mailbox2 transmit finished */ +#define CAN_TSTAT_MTFNERR2 BIT(17) /*!< mailbox2 transmit finished and no error */ +#define CAN_TSTAT_MAL2 BIT(18) /*!< mailbox2 arbitration lost */ +#define CAN_TSTAT_MTE2 BIT(19) /*!< mailbox2 transmit error */ +#define CAN_TSTAT_MST2 BIT(23) /*!< mailbox2 stop transmitting */ +#define CAN_TSTAT_NUM BITS(24,25) /*!< mailbox number */ +#define CAN_TSTAT_TME0 BIT(26) /*!< transmit mailbox0 empty */ +#define CAN_TSTAT_TME1 BIT(27) /*!< transmit mailbox1 empty */ +#define CAN_TSTAT_TME2 BIT(28) /*!< transmit mailbox2 empty */ +#define CAN_TSTAT_TMLS0 BIT(29) /*!< last sending priority flag for mailbox0 */ +#define CAN_TSTAT_TMLS1 BIT(30) /*!< last sending priority flag for mailbox1 */ +#define CAN_TSTAT_TMLS2 BIT(31) /*!< last sending priority flag for mailbox2 */ + +/* CAN_RFIFO0 */ +#define CAN_RFIFO0_RFL0 BITS(0,1) /*!< receive FIFO0 length */ +#define CAN_RFIFO0_RFF0 BIT(3) /*!< receive FIFO0 full */ +#define CAN_RFIFO0_RFO0 BIT(4) /*!< receive FIFO0 overfull */ +#define CAN_RFIFO0_RFD0 BIT(5) /*!< receive FIFO0 dequeue */ + +/* CAN_RFIFO1 */ +#define CAN_RFIFO1_RFL1 BITS(0,1) /*!< receive FIFO1 length */ +#define CAN_RFIFO1_RFF1 BIT(3) /*!< receive FIFO1 full */ +#define CAN_RFIFO1_RFO1 BIT(4) /*!< receive FIFO1 overfull */ +#define CAN_RFIFO1_RFD1 BIT(5) /*!< receive FIFO1 dequeue */ + +/* CAN_INTEN */ +#define CAN_INTEN_TMEIE BIT(0) /*!< transmit mailbox empty interrupt enable */ +#define CAN_INTEN_RFNEIE0 BIT(1) /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INTEN_RFFIE0 BIT(2) /*!< receive FIFO0 full interrupt enable */ +#define CAN_INTEN_RFOIE0 BIT(3) /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INTEN_RFNEIE1 BIT(4) /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INTEN_RFFIE1 BIT(5) /*!< receive FIFO1 full interrupt enable */ +#define CAN_INTEN_RFOIE1 BIT(6) /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INTEN_WERRIE BIT(8) /*!< warning error interrupt enable */ +#define CAN_INTEN_PERRIE BIT(9) /*!< passive error interrupt enable */ +#define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ +#define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ +#define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ + +/* CAN_ERR */ +#define CAN_ERR_WERR BIT(0) /*!< warning error */ +#define CAN_ERR_PERR BIT(1) /*!< passive error */ +#define CAN_ERR_BOERR BIT(2) /*!< bus-off error */ +#define CAN_ERR_ERRN BITS(4,6) /*!< error number */ +#define CAN_ERR_TECNT BITS(16,23) /*!< transmit error count */ +#define CAN_ERR_RECNT BITS(24,31) /*!< receive error count */ + +/* CAN_BT */ +#define CAN_BT_BAUDPSC BITS(0,9) /*!< baudrate prescaler */ +#define CAN_BT_BS1 BITS(16,19) /*!< bit segment 1 */ +#define CAN_BT_BS2 BITS(20,22) /*!< bit segment 2 */ +#define CAN_BT_SJW BITS(24,25) /*!< resynchronization jump width */ +#define CAN_BT_LCMOD BIT(30) /*!< loopback communication mode */ +#define CAN_BT_SCMOD BIT(31) /*!< silent communication mode */ + +/* CAN_TMIx */ +#define CAN_TMI_TEN BIT(0) /*!< transmit enable */ +#define CAN_TMI_FT BIT(1) /*!< frame type */ +#define CAN_TMI_FF BIT(2) /*!< frame format */ +#define CAN_TMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_TMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_TMPx */ +#define CAN_TMP_DLENC BITS(0,3) /*!< data length code */ +#define CAN_TMP_TSEN BIT(8) /*!< time stamp enable */ +#define CAN_TMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_TMDATA0x */ +#define CAN_TMDATA0_DB0 BITS(0,7) /*!< transmit data byte 0 */ +#define CAN_TMDATA0_DB1 BITS(8,15) /*!< transmit data byte 1 */ +#define CAN_TMDATA0_DB2 BITS(16,23) /*!< transmit data byte 2 */ +#define CAN_TMDATA0_DB3 BITS(24,31) /*!< transmit data byte 3 */ + +/* CAN_TMDATA1x */ +#define CAN_TMDATA1_DB4 BITS(0,7) /*!< transmit data byte 4 */ +#define CAN_TMDATA1_DB5 BITS(8,15) /*!< transmit data byte 5 */ +#define CAN_TMDATA1_DB6 BITS(16,23) /*!< transmit data byte 6 */ +#define CAN_TMDATA1_DB7 BITS(24,31) /*!< transmit data byte 7 */ + +/* CAN_RFIFOMIx */ +#define CAN_RFIFOMI_FT BIT(1) /*!< frame type */ +#define CAN_RFIFOMI_FF BIT(2) /*!< frame format */ +#define CAN_RFIFOMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_RFIFOMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_RFIFOMPx */ +#define CAN_RFIFOMP_DLENC BITS(0,3) /*!< receive data length code */ +#define CAN_RFIFOMP_FI BITS(8,15) /*!< filter index */ +#define CAN_RFIFOMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_RFIFOMDATA0x */ +#define CAN_RFIFOMDATA0_DB0 BITS(0,7) /*!< receive data byte 0 */ +#define CAN_RFIFOMDATA0_DB1 BITS(8,15) /*!< receive data byte 1 */ +#define CAN_RFIFOMDATA0_DB2 BITS(16,23) /*!< receive data byte 2 */ +#define CAN_RFIFOMDATA0_DB3 BITS(24,31) /*!< receive data byte 3 */ + +/* CAN_RFIFOMDATA1x */ +#define CAN_RFIFOMDATA1_DB4 BITS(0,7) /*!< receive data byte 4 */ +#define CAN_RFIFOMDATA1_DB5 BITS(8,15) /*!< receive data byte 5 */ +#define CAN_RFIFOMDATA1_DB6 BITS(16,23) /*!< receive data byte 6 */ +#define CAN_RFIFOMDATA1_DB7 BITS(24,31) /*!< receive data byte 7 */ + +/* CAN_FCTL */ +#define CAN_FCTL_FLD BIT(0) /*!< filter lock disable */ +#define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ + +/* CAN_FMCFG */ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ + +/* CAN_FSCFG */ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ + +/* CAN_FAFIFO */ +#define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ + +/* CAN_FW */ +#define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ + +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + +/* consts definitions */ +/* define the CAN bit position and its register index offset */ +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +#define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ +#define TSTAT_REG_OFFSET ((uint8_t)0x08U) /*!< TSTAT register offset */ +#define RFIFO0_REG_OFFSET ((uint8_t)0x0CU) /*!< RFIFO0 register offset */ +#define RFIFO1_REG_OFFSET ((uint8_t)0x10U) /*!< RFIFO1 register offset */ +#define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ + +/* CAN flags */ +typedef enum +{ + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + /* flags in TSTAT register */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + /* flags in RFIFO0 register */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + /* flags in RFIFO1 register */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + /* flags in ERR register */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +}can_flag_enum; + +/* CAN interrupt flags */ +typedef enum +{ + /* interrupt flags in STAT register */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +}can_interrupt_flag_enum; + +/* CAN initiliaze parameters struct */ +typedef struct +{ + uint8_t working_mode; /*!< CAN working mode */ + uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ + uint8_t time_segment_1; /*!< time segment 1 */ + uint8_t time_segment_2; /*!< time segment 2 */ + ControlStatus time_triggered; /*!< time triggered communication mode */ + ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ + ControlStatus auto_wake_up; /*!< automatic wake-up mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ + ControlStatus trans_fifo_order; /*!< transmit FIFO order */ + uint16_t prescaler; /*!< baudrate prescaler */ +}can_parameter_struct; + +/* CAN transmit message struct */ +typedef struct +{ + uint32_t tx_sfid; /*!< standard format frame identifier */ + uint32_t tx_efid; /*!< extended format frame identifier */ + uint8_t tx_ff; /*!< format of frame, standard or extended format */ + uint8_t tx_ft; /*!< type of frame, data or remote */ + uint8_t tx_dlen; /*!< data length */ + uint8_t tx_data[8]; /*!< transmit data */ +}can_trasnmit_message_struct; + +/* CAN receive message struct */ +typedef struct +{ + uint32_t rx_sfid; /*!< standard format frame identifier */ + uint32_t rx_efid; /*!< extended format frame identifier */ + uint8_t rx_ff; /*!< format of frame, standard or extended format */ + uint8_t rx_ft; /*!< type of frame, data or remote */ + uint8_t rx_dlen; /*!< data length */ + uint8_t rx_data[8]; /*!< receive data */ + uint8_t rx_fi; /*!< filtering index */ +} can_receive_message_struct; + +/* CAN filter parameters struct */ +typedef struct +{ + uint16_t filter_list_high; /*!< filter list number high bits*/ + uint16_t filter_list_low; /*!< filter list number low bits */ + uint16_t filter_mask_high; /*!< filter mask number high bits */ + uint16_t filter_mask_low; /*!< filter mask number low bits */ + uint16_t filter_fifo_number; /*!< receive FIFO associated with the filter */ + uint16_t filter_number; /*!< filter number */ + uint16_t filter_mode; /*!< filter mode, list or mask */ + uint16_t filter_bits; /*!< filter scale */ + ControlStatus filter_enable; /*!< filter work or not */ +}can_filter_parameter_struct; + +/* CAN errors */ +typedef enum +{ + CAN_ERROR_NONE = 0, /*!< no error */ + CAN_ERROR_FILL, /*!< fill error */ + CAN_ERROR_FORMATE, /*!< format error */ + CAN_ERROR_ACK, /*!< ACK error */ + CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ + CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ + CAN_ERROR_CRC, /*!< CRC error */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ +}can_error_enum; + +/* transmit states */ +typedef enum +{ + CAN_TRANSMIT_FAILED = 0U, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1U, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2U, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4U, /*!< no empty mailbox to be used for CAN */ +}can_transmit_state_enum; + +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + +/* CAN baudrate prescaler*/ +#define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) + +/* CAN bit segment 1*/ +#define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) + +/* CAN bit segment 2*/ +#define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) + +/* CAN resynchronization jump width*/ +#define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) + +/* CAN communication mode*/ +#define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) + +/* CAN FDATA high 16 bits */ +#define FDATA_MASK_HIGH(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) + +/* CAN FDATA low 16 bits */ +#define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) + +/* CAN1 filter start bank_number*/ +#define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) + +/* CAN transmit mailbox extended identifier*/ +#define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) + +/* CAN transmit mailbox standard identifier*/ +#define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) + +/* transmit data byte 0 */ +#define TMDATA0_DB0(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 1 */ +#define TMDATA0_DB1(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 2 */ +#define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 3 */ +#define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* transmit data byte 4 */ +#define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 5 */ +#define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 6 */ +#define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 7 */ +#define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* receive mailbox extended identifier*/ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3U, 31U) + +/* receive mailbox standrad identifier*/ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21U, 31U) + +/* receive data length */ +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0U, 3U) + +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 0 */ +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 1 */ +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 2 */ +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 3 */ +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* receive data byte 4 */ +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 5 */ +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 6 */ +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 7 */ +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4U, 6U) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* CAN errors */ +#define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) +#define CAN_ERRN_0 ERR_ERRN(0U) /* no error */ +#define CAN_ERRN_1 ERR_ERRN(1U) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2U) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3U) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4U) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5U) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6U) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7U) /*!< software error */ + +#define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ + +/* CAN communication mode */ +#define CAN_NORMAL_MODE ((uint8_t)0x00U) /*!< normal communication mode */ +#define CAN_LOOPBACK_MODE ((uint8_t)0x01U) /*!< loopback communication mode */ +#define CAN_SILENT_MODE ((uint8_t)0x02U) /*!< silent communication mode */ +#define CAN_SILENT_LOOPBACK_MODE ((uint8_t)0x03U) /*!< loopback and silent communication mode */ + +/* CAN resynchronisation jump width */ +#define CAN_BT_SJW_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_SJW_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_SJW_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_SJW_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ + +/* CAN time segment 1 */ +#define CAN_BT_BS1_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS1_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS1_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS1_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS1_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS1_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS1_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS1_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ +#define CAN_BT_BS1_9TQ ((uint8_t)0x08U) /*!< 9 time quanta */ +#define CAN_BT_BS1_10TQ ((uint8_t)0x09U) /*!< 10 time quanta */ +#define CAN_BT_BS1_11TQ ((uint8_t)0x0AU) /*!< 11 time quanta */ +#define CAN_BT_BS1_12TQ ((uint8_t)0x0BU) /*!< 12 time quanta */ +#define CAN_BT_BS1_13TQ ((uint8_t)0x0CU) /*!< 13 time quanta */ +#define CAN_BT_BS1_14TQ ((uint8_t)0x0DU) /*!< 14 time quanta */ +#define CAN_BT_BS1_15TQ ((uint8_t)0x0EU) /*!< 15 time quanta */ +#define CAN_BT_BS1_16TQ ((uint8_t)0x0FU) /*!< 16 time quanta */ + +/* CAN time segment 2 */ +#define CAN_BT_BS2_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS2_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS2_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS2_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS2_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS2_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS2_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS2_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ + +/* CAN mailbox number */ +#define CAN_MAILBOX0 ((uint8_t)0x00U) /*!< mailbox0 */ +#define CAN_MAILBOX1 ((uint8_t)0x01U) /*!< mailbox1 */ +#define CAN_MAILBOX2 ((uint8_t)0x02U) /*!< mailbox2 */ +#define CAN_NOMAILBOX ((uint8_t)0x03U) /*!< no mailbox empty */ + +/* CAN frame format */ +#define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ +#define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ + +/* CAN receive fifo */ +#define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ +#define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ + +/* frame number of receive fifo */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ + +#define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ +#define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ + +/* CAN working mode */ +#define CAN_MODE_INITIALIZE ((uint8_t)0x01U) /*!< CAN initialize mode */ +#define CAN_MODE_NORMAL ((uint8_t)0x02U) /*!< CAN normal mode */ +#define CAN_MODE_SLEEP ((uint8_t)0x04U) /*!< CAN sleep mode */ + +/* filter bits */ +#define CAN_FILTERBITS_16BIT ((uint8_t)0x00U) /*!< CAN filter 16 bits */ +#define CAN_FILTERBITS_32BIT ((uint8_t)0x01U) /*!< CAN filter 32 bits */ + +/* filter mode */ +#define CAN_FILTERMODE_MASK ((uint8_t)0x00U) /*!< mask mode */ +#define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ + +/* filter 16 bits mask */ +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ + +/* frame type */ +#define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ +#define CAN_FT_REMOTE ((uint32_t)0x00000002U) /*!< remote frame */ + +/* CAN timeout */ +#define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ + +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + +/* function declarations */ +/* deinitialize CAN */ +void can_deinit(uint32_t can_periph); +/* initialize CAN struct */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +/* CAN filter init */ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); +/* set can1 fliter start bank number */ +void can1_filter_start_bank(uint8_t start_bank); +/* enable functions */ +/* CAN debug freeze enable */ +void can_debug_freeze_enable(uint32_t can_periph); +/* CAN debug freeze disable */ +void can_debug_freeze_disable(uint32_t can_periph); +/* CAN time trigger mode enable */ +void can_time_trigger_mode_enable(uint32_t can_periph); +/* CAN time trigger mode disable */ +void can_time_trigger_mode_disable(uint32_t can_periph); + +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); +/* CAN receive message */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); +/* CAN release fifo */ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); +/* CAN receive message length */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); +/* CAN working mode */ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); +/* CAN wakeup from sleep mode */ +ErrStatus can_wakeup(uint32_t can_periph); + +/* CAN get error */ +can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); +/* CAN get flag state */ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); +/* CAN clear flag state */ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN get interrupt flag state */ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); +/* CAN clear interrupt flag state */ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag); + +#endif /* GD32F30X_CAN_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h new file mode 100644 index 0000000000..bc3c43ffe4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h @@ -0,0 +1,81 @@ +/*! + \file gd32f30x_crc.h + \brief definitions for the CRC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_CRC_H +#define GD32F30X_CRC_H + +#include "gd32f30x.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0,31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0,7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + + +/* function declarations */ +/* deinit CRC calculation unit */ +void crc_deinit(void); + +/* reset data register(CRC_DATA) to the value of 0xFFFFFFFF */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); + +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(const uint32_t *array, uint32_t size); + +#endif /* GD32F30X_CRC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h new file mode 100644 index 0000000000..5602447bad --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h @@ -0,0 +1,186 @@ +/*! + \file gd32f30x_ctc.h + \brief definitions for the CTC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_CTC_H +#define GD32F30X_CTC_H + +#include "gd32f30x.h" + +/* CTC definitions */ +#define CTC CTC_BASE + +/* registers definitions */ +#define CTC_CTL0 REG32((CTC) + 0x00U) /*!< CTC control register 0 */ +#define CTC_CTL1 REG32((CTC) + 0x04U) /*!< CTC control register 1 */ +#define CTC_STAT REG32((CTC) + 0x08U) /*!< CTC status register */ +#define CTC_INTC REG32((CTC) + 0x0CU) /*!< CTC interrupt clear register */ + +/* bits definitions */ +/* CTC_CTL0 */ +#define CTC_CTL0_CKOKIE BIT(0) /*!< clock trim OK(CKOKIF) interrupt enable */ +#define CTC_CTL0_CKWARNIE BIT(1) /*!< clock trim warning(CKWARNIF) interrupt enable */ +#define CTC_CTL0_ERRIE BIT(2) /*!< error(ERRIF) interrupt enable */ +#define CTC_CTL0_EREFIE BIT(3) /*!< EREFIF interrupt enable */ +#define CTC_CTL0_CNTEN BIT(5) /*!< CTC counter enable */ +#define CTC_CTL0_AUTOTRIM BIT(6) /*!< hardware automatically trim mode */ +#define CTC_CTL0_SWREFPUL BIT(7) /*!< software reference source sync pulse */ +#define CTC_CTL0_TRIMVALUE BITS(8,13) /*!< IRC48M trim value */ + +/* CTC_CTL1 */ +#define CTC_CTL1_RLVALUE BITS(0,15) /*!< CTC counter reload value */ +#define CTC_CTL1_CKLIM BITS(16,23) /*!< clock trim base limit value */ +#define CTC_CTL1_REFPSC BITS(24,26) /*!< reference signal source prescaler */ +#define CTC_CTL1_REFSEL BITS(28,29) /*!< reference signal source selection */ +#define CTC_CTL1_REFPOL BIT(31) /*!< reference signal source polarity */ + +/* CTC_STAT */ +#define CTC_STAT_CKOKIF BIT(0) /*!< clock trim OK interrupt flag */ +#define CTC_STAT_CKWARNIF BIT(1) /*!< clock trim warning interrupt flag */ +#define CTC_STAT_ERRIF BIT(2) /*!< error interrupt flag */ +#define CTC_STAT_EREFIF BIT(3) /*!< expect reference interrupt flag */ +#define CTC_STAT_CKERR BIT(8) /*!< clock trim error bit */ +#define CTC_STAT_REFMISS BIT(9) /*!< reference sync pulse miss */ +#define CTC_STAT_TRIMERR BIT(10) /*!< trim value error bit */ +#define CTC_STAT_REFDIR BIT(15) /*!< CTC trim counter direction when reference sync pulse occurred */ +#define CTC_STAT_REFCAP BITS(16,31) /*!< CTC counter capture when reference sync pulse occurred */ + +/* CTC_INTC */ +#define CTC_INTC_CKOKIC BIT(0) /*!< CKOKIF interrupt clear bit */ +#define CTC_INTC_CKWARNIC BIT(1) /*!< CKWARNIF interrupt clear bit */ +#define CTC_INTC_ERRIC BIT(2) /*!< ERRIF interrupt clear bit */ +#define CTC_INTC_EREFIC BIT(3) /*!< EREFIF interrupt clear bit */ + +/* constants definitions */ +/* hardware automatically trim mode definitions */ +#define CTC_HARDWARE_TRIM_MODE_ENABLE CTC_CTL0_AUTOTRIM /*!< hardware automatically trim mode enable*/ +#define CTC_HARDWARE_TRIM_MODE_DISABLE ((uint32_t)0x00000000U) /*!< hardware automatically trim mode disable*/ + +/* reference signal source polarity definitions */ +#define CTC_REFSOURCE_POLARITY_FALLING CTC_CTL1_REFPOL /*!< reference signal source polarity is falling edge*/ +#define CTC_REFSOURCE_POLARITY_RISING ((uint32_t)0x00000000U) /*!< reference signal source polarity is rising edge*/ + +/* reference signal source selection definitions */ +#define CTL1_REFSEL(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define CTC_REFSOURCE_GPIO CTL1_REFSEL(0) /*!< GPIO is selected */ +#define CTC_REFSOURCE_LXTAL CTL1_REFSEL(1) /*!< LXTAL is selected */ +#define CTC_REFSOURCE_USB_SOF CTL1_REFSEL(2) /*!< USBD_SOF or USBFS_SOF is selected */ + +/* reference signal source prescaler definitions */ +#define CTL1_REFPSC(regval) (BITS(24,26) & ((uint32_t)(regval) << 24)) +#define CTC_REFSOURCE_PSC_OFF CTL1_REFPSC(0) /*!< reference signal not divided */ +#define CTC_REFSOURCE_PSC_DIV2 CTL1_REFPSC(1) /*!< reference signal divided by 2 */ +#define CTC_REFSOURCE_PSC_DIV4 CTL1_REFPSC(2) /*!< reference signal divided by 4 */ +#define CTC_REFSOURCE_PSC_DIV8 CTL1_REFPSC(3) /*!< reference signal divided by 8 */ +#define CTC_REFSOURCE_PSC_DIV16 CTL1_REFPSC(4) /*!< reference signal divided by 16 */ +#define CTC_REFSOURCE_PSC_DIV32 CTL1_REFPSC(5) /*!< reference signal divided by 32 */ +#define CTC_REFSOURCE_PSC_DIV64 CTL1_REFPSC(6) /*!< reference signal divided by 64 */ +#define CTC_REFSOURCE_PSC_DIV128 CTL1_REFPSC(7) /*!< reference signal divided by 128 */ + +/* CTC interrupt enable definitions */ +#define CTC_INT_CKOK CTC_CTL0_CKOKIE /*!< clock trim OK interrupt enable */ +#define CTC_INT_CKWARN CTC_CTL0_CKWARNIE /*!< clock trim warning interrupt enable */ +#define CTC_INT_ERR CTC_CTL0_ERRIE /*!< error interrupt enable */ +#define CTC_INT_EREF CTC_CTL0_EREFIE /*!< expect reference interrupt enable */ + +/* CTC interrupt source definitions */ +#define CTC_INT_FLAG_CKOK CTC_STAT_CKOKIF /*!< clock trim OK interrupt flag */ +#define CTC_INT_FLAG_CKWARN CTC_STAT_CKWARNIF /*!< clock trim warning interrupt flag */ +#define CTC_INT_FLAG_ERR CTC_STAT_ERRIF /*!< error interrupt flag */ +#define CTC_INT_FLAG_EREF CTC_STAT_EREFIF /*!< expect reference interrupt flag */ +#define CTC_INT_FLAG_CKERR CTC_STAT_CKERR /*!< clock trim error bit */ +#define CTC_INT_FLAG_REFMISS CTC_STAT_REFMISS /*!< reference sync pulse miss */ +#define CTC_INT_FLAG_TRIMERR CTC_STAT_TRIMERR /*!< trim value error */ + +/* CTC flag definitions */ +#define CTC_FLAG_CKOK CTC_STAT_CKOKIF /*!< clock trim OK flag */ +#define CTC_FLAG_CKWARN CTC_STAT_CKWARNIF /*!< clock trim warning flag */ +#define CTC_FLAG_ERR CTC_STAT_ERRIF /*!< error flag */ +#define CTC_FLAG_EREF CTC_STAT_EREFIF /*!< expect reference flag */ +#define CTC_FLAG_CKERR CTC_STAT_CKERR /*!< clock trim error bit */ +#define CTC_FLAG_REFMISS CTC_STAT_REFMISS /*!< reference sync pulse miss */ +#define CTC_FLAG_TRIMERR CTC_STAT_TRIMERR /*!< trim value error bit */ + +/* function declarations */ +/* reset ctc clock trim controller */ +void ctc_deinit(void); +/* enable CTC trim counter */ +void ctc_counter_enable(void); +/* disable CTC trim counter */ +void ctc_counter_disable(void); + +/* configure the IRC48M trim value */ +void ctc_irc48m_trim_value_config(uint8_t trim_value); +/* generate software reference source sync pulse */ +void ctc_software_refsource_pulse_generate(void); +/* configure hardware automatically trim mode */ +void ctc_hardware_trim_mode_config(uint32_t hardmode); + +/* configure reference signal source polarity */ +void ctc_refsource_polarity_config(uint32_t polarity); +/* select reference signal source */ +void ctc_refsource_signal_select(uint32_t refs); +/* configure reference signal source prescaler */ +void ctc_refsource_prescaler_config(uint32_t prescaler); +/* configure clock trim base limit value */ +void ctc_clock_limit_value_config(uint8_t limit_value); +/* configure CTC counter reload value */ +void ctc_counter_reload_value_config(uint16_t reload_value); + +/* read CTC counter capture value when reference sync pulse occurred */ +uint16_t ctc_counter_capture_value_read(void); +/* read CTC trim counter direction when reference sync pulse occurred */ +FlagStatus ctc_counter_direction_read(void); +/* read CTC counter reload value */ +uint16_t ctc_counter_reload_value_read(void); +/* read the IRC48M trim value */ +uint8_t ctc_irc48m_trim_value_read(void); + +/* interrupt & flag functions */ +/* enable the CTC interrupt */ +void ctc_interrupt_enable(uint32_t interrupt); +/* disable the CTC interrupt */ +void ctc_interrupt_disable(uint32_t interrupt); +/* get CTC interrupt flag */ +FlagStatus ctc_interrupt_flag_get(uint32_t int_flag); +/* clear CTC interrupt flag */ +void ctc_interrupt_flag_clear(uint32_t int_flag); +/* get CTC flag */ +FlagStatus ctc_flag_get(uint32_t flag); +/* clear CTC flag */ +void ctc_flag_clear(uint32_t flag); + +#endif /* GD32F30X_CTC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h new file mode 100644 index 0000000000..f2d3b2d693 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h @@ -0,0 +1,250 @@ +/*! + \file gd32f30x_dac.h + \brief definitions for the DAC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_DAC_H +#define GD32F30X_DAC_H + +#include "gd32f30x.h" + +/* DACx(x=0,1) definitions */ +#define DAC DAC_BASE +#define DAC0 0U +#define DAC1 1U + +/* registers definitions */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ + +/* bits definitions */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ + +/* DAC_SWT */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ + +/* DAC0_R12DH */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ + +/* DAC0_L12DH */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ + +/* DAC0_R8DH */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ + +/* DAC1_R12DH */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ + +/* DAC1_L12DH */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ + +/* DAC1_R8DH */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ + +/* DACC_R12DH */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ + +/* DACC_L12DH */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ + +/* DACC_R8DH */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ + +/* DAC0_DO */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ + +/* DAC1_DO */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ + +/* constants definitions */ +/* DAC trigger source */ +#define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define DAC_TRIGGER_T7_TRGO CTL_DTSEL(1) /*!< TIMER7 TRGO */ +#elif defined(GD32F30X_CL) +#define DAC_TRIGGER_T2_TRGO CTL_DTSEL(1) /*!< TIMER2 TRGO */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ + +/* DAC noise wave mode */ +#define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ + +/* DAC noise wave bit width */ +#define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ + +/* unmask LFSR bits in DAC LFSR noise mode */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ + +/* DAC data alignment */ +#define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12 bit alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12 bit alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8 bit alignment */ + +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DAC */ +void dac_deinit(void); +/* enable DAC */ +void dac_enable(uint32_t dac_periph); +/* disable DAC */ +void dac_disable(uint32_t dac_periph); +/* enable DAC DMA */ +void dac_dma_enable(uint32_t dac_periph); +/* disable DAC DMA */ +void dac_dma_disable(uint32_t dac_periph); +/* enable DAC output buffer */ +void dac_output_buffer_enable(uint32_t dac_periph); +/* disable DAC output buffer */ +void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* DAC trigger configuration */ +/* enable DAC trigger */ +void dac_trigger_enable(uint32_t dac_periph); +/* disable DAC trigger */ +void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* enable DAC software trigger */ +void dac_software_trigger_enable(uint32_t dac_periph); +/* disable DAC software trigger */ +void dac_software_trigger_disable(uint32_t dac_periph); + +/* DAC wave mode configuration */ +/* configure DAC wave mode */ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); +/* configure DAC wave bit width */ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); +/* configure DAC LFSR noise mode */ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); +/* configure DAC triangle noise mode */ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); + +/* DAC concurrent mode configuration */ +/* enable DAC concurrent mode */ +void dac_concurrent_enable(void); +/* disable DAC concurrent mode */ +void dac_concurrent_disable(void); +/* enable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_enable(void); +/* disable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_disable(void); +/* enable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_enable(void); +/* disable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); + +#endif /* GD32F30X_DAC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h new file mode 100644 index 0000000000..7129eacc16 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h @@ -0,0 +1,158 @@ +/*! + \file gd32f30x_dbg.h + \brief definitions for the DBG + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_DBG_H +#define GD32F30X_DBG_H + +#include "gd32f30x.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL0 REG32(DBG + 0x04U) /*!< DBG control register 0 */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ + +/* DBG_CTL0 */ +#define DBG_CTL0_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL0_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL0_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL0_TRACE_IOEN BIT(5) /*!< enable trace pin assignment */ +#define DBG_CTL0_TRACE_MODE BITS(6,7) /*!< trace pin mode selection */ +#define DBG_CTL0_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL0_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL0_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL0_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL0_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL0_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL0_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL0_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL0_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL0_TIMER7_HOLD BIT(17) /*!< hold TIMER7 counter when core is halted */ +#define DBG_CTL0_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL0_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL0_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F30X_CL +#define DBG_CTL0_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD +#define DBG_CTL0_TIMER11_HOLD BIT(25) /*!< hold TIMER11 counter when core is halted */ +#define DBG_CTL0_TIMER12_HOLD BIT(26) /*!< hold TIMER12 counter when core is halted */ +#define DBG_CTL0_TIMER13_HOLD BIT(27) /*!< hold TIMER13 counter when core is halted */ +#define DBG_CTL0_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ +#define DBG_CTL0_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ +#define DBG_CTL0_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F30X_HD */ + +/* constants definitions */ +#define DBG_LOW_POWER_SLEEP DBG_CTL0_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL0_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL0_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* define the peripheral debug hold bit position and its register index offset */ +#define DBG_REGIDX_BIT(regidx, bitpos) (((regidx) << 6) | (bitpos)) +#define DBG_REG_VAL(periph) (REG32(DBG + ((uint32_t)(periph) >> 6))) +#define DBG_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register index */ +enum dbg_reg_idx +{ + DBG_IDX_CTL0 = 0x04U +}; + +typedef enum +{ + DBG_FWDGT_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 8U), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 9U), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 10U), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 11U), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 12U), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 13U), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 14U), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 15U), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 16U), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 17U), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 18U), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 19U), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 20U), /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F30X_CL + DBG_CAN1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 21U), /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD + DBG_TIMER11_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 25U), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 26U), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 27U), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 28U), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 29U), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 30U), /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F30X_HD */ +}dbg_periph_enum; + +#define CTL0_TRACE_MODE(regval) (BITS(6,7)&((uint32_t)(regval)<<6)) +#define TRACE_MODE_ASYNC CTL0_TRACE_MODE(0) /*!< trace pin used for async mode */ +#define TRACE_MODE_SYNC_DATASIZE_1 CTL0_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ +#define TRACE_MODE_SYNC_DATASIZE_2 CTL0_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ +#define TRACE_MODE_SYNC_DATASIZE_4 CTL0_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ + +/* function declarations */ +/* deinitialize the DBG */ +void dbg_deinit(void); +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +/* enable trace pin assignment */ +void dbg_trace_pin_enable(void); +/* disable trace pin assignment */ +void dbg_trace_pin_disable(void); +/* set trace pin mode */ +void dbg_trace_pin_mode_set(uint32_t trace_mode); + +#endif /* GD32F30X_DBG_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h new file mode 100644 index 0000000000..73b1a516fe --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h @@ -0,0 +1,285 @@ +/*! + \file gd32f30x_dma.h + \brief definitions for the DMA + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_DMA_H +#define GD32F30X_DMA_H + +#include "gd32f30x.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT,x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ + +/* DMA_CHxPADDR,x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ + +/* DMA_CHxMADDR,x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum +{ + DMA_CH0 = 0, /*!< DMA Channel0 */ + DMA_CH1, /*!< DMA Channel1 */ + DMA_CH2, /*!< DMA Channel2 */ + DMA_CH3, /*!< DMA Channel3 */ + DMA_CH4, /*!< DMA Channel4 */ + DMA_CH5, /*!< DMA Channel5 */ + DMA_CH6 /*!< DMA Channel6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x0000U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x0001U) /*!< read from memory and write to peripheral */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x0000U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x0001U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x0000U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x0001U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* DMA deinitialization and initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA struct with the default values */ +void dma_struct_para_init(dma_parameter_struct* init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increasement algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increasement algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear DMA a channel flag */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear DMA a channel flag */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +#endif /* GD32F30X_DMA_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h new file mode 100644 index 0000000000..1b3ca7cfdc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h @@ -0,0 +1,1702 @@ +/*! + \file gd32f30x_enet.h + \brief definitions for the ENET + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-04-02, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_ENET_H +#define GD32F30X_ENET_H + +#include "gd32f30x.h" + +#define IF_USE_EXTERNPHY_LIB 0 +#if (1 == IF_USE_EXTERNPHY_LIB) +#include "phy.h" +#endif + +#ifndef ENET_RXBUF_NUM +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ +#endif + +#ifndef ENET_TXBUF_NUM +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ +#endif + +#ifndef ENET_RXBUF_SIZE +#define ENET_RXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet receive buffer size */ +#endif + +#ifndef ENET_TXBUF_SIZE +#define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ +#endif + +/* #define SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* #define USE_DELAY */ + +#ifndef _PHY_H_ +#define DP83848 0 +#define LAN8700 1 +#define PHY_TYPE DP83848 + +#define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ + +/* PHY read write timeouts */ +#define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ +#define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ + +/* PHY delay */ +#define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ +#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ + +/* PHY register address */ +#define PHY_REG_BCR 0U /*!< tranceiver basic control register */ +#define PHY_REG_BSR 1U /*!< tranceiver basic status register */ + +/* PHY basic control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ + +#if(PHY_TYPE == LAN8700) +#define PHY_SR 31U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#elif(PHY_TYPE == DP83848) +#define PHY_SR 16U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#endif /* PHY_TYPE */ + +#endif /* _PHY_H_ */ + + +/* ENET definitions */ +#define ENET ENET_BASE + +/* registers definitions */ +#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_DBG REG32((ENET) + 0x34U) /*!< ethernet MAC debug register */ +#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ +#define ENET_PTP_TSF REG32((ENET) + 0x728U) /*!< ethernet PTP time stamp flag register */ +#define ENET_PTP_PPSCTL REG32((ENET) + 0x72CU) /*!< ethernet PTP PPS control register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_RSWDC REG32((ENET) + 0x1024U) /*!< ethernet DMA receive state watchdog counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ + +/* bits definitions */ +/* ENET_MAC_CFG */ +#define ENET_MAC_CFG_REN BIT(2) /*!< receiver enable */ +#define ENET_MAC_CFG_TEN BIT(3) /*!< transmitter enable */ +#define ENET_MAC_CFG_DFC BIT(4) /*!< defferal check */ +#define ENET_MAC_CFG_BOL BITS(5,6) /*!< back-off limit */ +#define ENET_MAC_CFG_APCD BIT(7) /*!< automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD BIT(9) /*!< retry disable */ +#define ENET_MAC_CFG_IPFCO BIT(10) /*!< IP frame checksum offload */ +#define ENET_MAC_CFG_DPM BIT(11) /*!< duplex mode */ +#define ENET_MAC_CFG_LBM BIT(12) /*!< loopback mode */ +#define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ +#define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ +#define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ +#define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ +#define ENET_MAC_CFG_TFCD BIT(25) /*!< type frame CRC dropping */ + +/* ENET_MAC_FRMF */ +#define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ +#define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + +/* ENET_MAC_HLH */ +#define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ + +/* ENET_MAC_HLL */ +#define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ + +/* ENET_MAC_PHY_CTL */ +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + +/* ENET_MAC_PHY_DATA */ +#define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ + +/* ENET_MAC_FCTL */ +#define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ +#define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ + +/* ENET_MAC_VLT */ +#define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ + +/* ENET_MAC_RWFF */ +#define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ + +/* ENET_MAC_WUM */ +#define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ +#define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ +#define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ +#define ENET_MAC_WUM_MPKR BIT(5) /*!< magic packet received */ +#define ENET_MAC_WUM_WUFR BIT(6) /*!< wakeup frame received */ +#define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ +#define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ + +/* ENET_MAC_DBG */ +#define ENET_MAC_DBG_MRNI BIT(0) /*!< MAC receive state not idle */ +#define ENET_MAC_DBG_RXAFS BITS(1,2) /*!< Rx asynchronous FIFO status */ +#define ENET_MAC_DBG_RXFW BIT(4) /*!< RxFIFO is writing */ +#define ENET_MAC_DBG_RXFRS BITS(5,6) /*!< RxFIFO read operation status */ +#define ENET_MAC_DBG_RXFS BITS(8,9) /*!< RxFIFO state */ +#define ENET_MAC_DBG_MTNI BIT(16) /*!< MAC transmit state not idle */ +#define ENET_MAC_DBG_SOMT BITS(17,18) /*!< status of mac transmitter */ +#define ENET_MAC_DBG_PCS BIT(19) /*!< pause condition status */ +#define ENET_MAC_DBG_TXFRS BITS(20,21) /*!< TxFIFO read operation status */ +#define ENET_MAC_DBG_TXFW BIT(22) /*!< TxFIFO is writing */ +#define ENET_MAC_DBG_TXFNE BIT(24) /*!< TxFIFO not empty flag */ +#define ENET_MAC_DBG_TXFF BIT(25) /*!< TxFIFO full flag */ + +/* ENET_MAC_INTF */ +#define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ +#define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ +#define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ +#define ENET_MAC_INTF_MSCT BIT(6) /*!< MSC transmit status */ +#define ENET_MAC_INTF_TMST BIT(9) /*!< timestamp trigger status */ + +/* ENET_MAC_INTMSK */ +#define ENET_MAC_INTMSK_WUMIM BIT(3) /*!< WUM interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM BIT(9) /*!< timestamp trigger interrupt mask */ + +/* ENET_MAC_ADDR0H */ +#define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ +#define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ + +/* ENET_MAC_ADDR0L */ +#define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ + +/* ENET_MAC_ADDR1H */ +#define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR1L */ +#define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ + +/* ENET_MAC_ADDR2H */ +#define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ +#define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR2L */ +#define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ + +/* ENET_MAC_ADDR3H */ +#define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ +#define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR3H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR3H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR3L */ +#define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ + +/* ENET_MAC_FCTH */ +#define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ +#define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ + +/* ENET_MSC_CTL */ +#define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ +#define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ +#define ENET_MSC_CTL_RTOR BIT(2) /*!< reset on read */ +#define ENET_MSC_CTL_MCFZ BIT(3) /*!< MSC counter freeze */ +#define ENET_MSC_CTL_PMC BIT(4) /*!< preset MSC counter */ +#define ENET_MSC_CTL_AFHPM BIT(5) /*!< almost full or half preset mode */ + +/* ENET_MSC_RINTF */ +#define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ +#define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ +#define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ + +/* ENET_MSC_TINTF */ +#define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ +#define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ +#define ENET_MSC_TINTF_TGF BIT(21) /*!< transmitted good frames */ + +/* ENET_MSC_RINTMSK */ +#define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ + +/* ENET_MSC_TINTMSK */ +#define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ + +/* ENET_MSC_SCCNT */ +#define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ + +/* ENET_MSC_MSCCNT */ +#define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ + +/* ENET_MSC_TGFCNT */ +#define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ + +/* ENET_MSC_RFCECNT */ +#define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ + +/* ENET_MSC_RFAECNT */ +#define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ + +/* ENET_MSC_RGUFCNT */ +#define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ + +/* ENET_PTP_TSCTL */ +#define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI BIT(2) /*!< timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU BIT(3) /*!< timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN BIT(4) /*!< timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU BIT(5) /*!< timestamp addend register update */ +#define ENET_PTP_TSCTL_ARFSEN BIT(8) /*!< all received frames snapshot enable */ +#define ENET_PTP_TSCTL_SCROM BIT(9) /*!< subsecond counter rollover mode */ +#define ENET_PTP_TSCTL_PFSV BIT(10) /*!< PTP frame snooping version */ +#define ENET_PTP_TSCTL_ESEN BIT(11) /*!< received Ethernet snapshot enable */ +#define ENET_PTP_TSCTL_IP6SEN BIT(12) /*!< received IPv6 snapshot enable */ +#define ENET_PTP_TSCTL_IP4SEN BIT(13) /*!< received IPv4 snapshot enable */ +#define ENET_PTP_TSCTL_ETMSEN BIT(14) /*!< received event type message snapshot enable */ +#define ENET_PTP_TSCTL_MNMSEN BIT(15) /*!< received master node message snapshot enable */ +#define ENET_PTP_TSCTL_CKNT BITS(16,17) /*!< clock node type for time stamp */ +#define ENET_PTP_TSCTL_MAFEN BIT(18) /*!< MAC address filter enable for PTP frame */ + +/* ENET_PTP_SSINC */ +#define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ + +/* ENET_PTP_TSH */ +#define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ + +/* ENET_PTP_TSL */ +#define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ +#define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ + +/* ENET_PTP_TSUH */ +#define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ + +/* ENET_PTP_TSUL */ +#define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ +#define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ + +/* ENET_PTP_TSADDEND */ +#define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ + +/* ENET_PTP_ETH */ +#define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ + +/* ENET_PTP_ETL */ +#define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ + +/* ENET_PTP_TSF */ +#define ENET_PTP_TSF_TSSCO BIT(0) /*!< timestamp second counter overflow */ +#define ENET_PTP_TSF_TTM BIT(1) /*!< target time match */ + +/* ENET_PTP_PPSCTL */ +#define ENET_PTP_PPSCTL_PPSOFC BITS(0,3) /*!< PPS output frequency configure */ + +/* ENET_DMA_BCTL */ +#define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ +#define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ +#define ENET_DMA_BCTL_DPSL BITS(2,6) /*!< descriptor skip length */ +#define ENET_DMA_BCTL_DFM BIT(7) /*!< descriptor format mode */ +#define ENET_DMA_BCTL_PGBL BITS(8,13) /*!< programmable burst length */ +#define ENET_DMA_BCTL_RTPR BITS(14,15) /*!< RxDMA and TxDMA transfer priority ratio */ +#define ENET_DMA_BCTL_FB BIT(16) /*!< fixed Burst */ +#define ENET_DMA_BCTL_RXDP BITS(17,22) /*!< RxDMA PGBL */ +#define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ +#define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ +#define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ +#define ENET_DMA_BCTL_MB BIT(26) /*!< mixed burst */ + +/* ENET_DMA_TPEN */ +#define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ + +/* ENET_DMA_RPEN */ +#define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ + +/* ENET_DMA_RDTADDR */ +#define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ + +/* ENET_DMA_TDTADDR */ +#define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ + +/* ENET_DMA_STAT */ +#define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ +#define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ +#define ENET_DMA_STAT_TBU BIT(2) /*!< transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT BIT(3) /*!< transmit jabber timeout status */ +#define ENET_DMA_STAT_RO BIT(4) /*!< receive overflow status */ +#define ENET_DMA_STAT_TU BIT(5) /*!< transmit underflow status */ +#define ENET_DMA_STAT_RS BIT(6) /*!< receive status */ +#define ENET_DMA_STAT_RBU BIT(7) /*!< receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS BIT(8) /*!< receive process stopped status */ +#define ENET_DMA_STAT_RWT BIT(9) /*!< receive watchdog timeout status */ +#define ENET_DMA_STAT_ET BIT(10) /*!< early transmit status */ +#define ENET_DMA_STAT_FBE BIT(13) /*!< fatal bus error status */ +#define ENET_DMA_STAT_ER BIT(14) /*!< early receive status */ +#define ENET_DMA_STAT_AI BIT(15) /*!< abnormal interrupt summary */ +#define ENET_DMA_STAT_NI BIT(16) /*!< normal interrupt summary */ +#define ENET_DMA_STAT_RP BITS(17,19) /*!< receive process state */ +#define ENET_DMA_STAT_TP BITS(20,22) /*!< transmit process state */ +#define ENET_DMA_STAT_EB BITS(23,25) /*!< error bits status */ +#define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ +#define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ +#define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ + +/* ENET_DMA_CTL */ +#define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ +#define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ +#define ENET_DMA_CTL_RTHC BITS(3,4) /*!< receive threshold control */ +#define ENET_DMA_CTL_FUF BIT(6) /*!< forward undersized good frames */ +#define ENET_DMA_CTL_FERF BIT(7) /*!< forward error frames */ +#define ENET_DMA_CTL_STE BIT(13) /*!< start/stop transmission enable */ +#define ENET_DMA_CTL_TTHC BITS(14,16) /*!< transmit threshold control */ +#define ENET_DMA_CTL_FTF BIT(20) /*!< flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD BIT(21) /*!< transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ + +/* ENET_DMA_INTEN */ +#define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE BIT(2) /*!< transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE BIT(3) /*!< transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE BIT(4) /*!< receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE BIT(5) /*!< transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE BIT(6) /*!< receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE BIT(7) /*!< receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE BIT(8) /*!< receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE BIT(9) /*!< receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE BIT(10) /*!< early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE BIT(13) /*!< fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ + +/* ENET_DMA_MFBOCNT */ +#define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ +#define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ + +/* ENET_DMA_RSWDC */ +#define ENET_DMA_RSWDC_WDCFRS BITS(0,7) /*!< watchdog counter for receive status (RS) */ + +/* ENET_DMA_CTDADDR */ +#define ENET_DMA_CTDADDR_TDAP BITS(0,31) /*!< transmit descriptor address pointer */ + +/* ENET_DMA_CRDADDR */ +#define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ + +/* ENET_DMA_CTBADDR */ +#define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ + +/* ENET_DMA_CRBADDR */ +#define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ + +/* ENET DMA Tx descriptor TDES0 */ +#define ENET_TDES0_DB BIT(0) /*!< deferred */ +#define ENET_TDES0_UFE BIT(1) /*!< underflow error */ +#define ENET_TDES0_EXD BIT(2) /*!< excessive deferral */ +#define ENET_TDES0_COCNT BITS(3,6) /*!< collision count */ +#define ENET_TDES0_VFRM BIT(7) /*!< VLAN frame */ +#define ENET_TDES0_ECO BIT(8) /*!< excessive collision */ +#define ENET_TDES0_LCO BIT(9) /*!< late collision */ +#define ENET_TDES0_NCA BIT(10) /*!< no carrier */ +#define ENET_TDES0_LCA BIT(11) /*!< loss of carrier */ +#define ENET_TDES0_IPPE BIT(12) /*!< IP payload error */ +#define ENET_TDES0_FRMF BIT(13) /*!< frame flushed */ +#define ENET_TDES0_JT BIT(14) /*!< jabber timeout */ +#define ENET_TDES0_ES BIT(15) /*!< error summary */ +#define ENET_TDES0_IPHE BIT(16) /*!< IP header error */ +#define ENET_TDES0_TTMSS BIT(17) /*!< transmit timestamp status */ +#define ENET_TDES0_TCHM BIT(20) /*!< the second address chained mode */ +#define ENET_TDES0_TERM BIT(21) /*!< transmit end of ring mode*/ +#define ENET_TDES0_CM BITS(22,23) /*!< checksum mode */ +#define ENET_TDES0_TTSEN BIT(25) /*!< transmit timestamp function enable */ +#define ENET_TDES0_DPAD BIT(26) /*!< disable adding pad */ +#define ENET_TDES0_DCRC BIT(27) /*!< disable CRC */ +#define ENET_TDES0_FSG BIT(28) /*!< first segment */ +#define ENET_TDES0_LSG BIT(29) /*!< last segment */ +#define ENET_TDES0_INTC BIT(30) /*!< interrupt on completion */ +#define ENET_TDES0_DAV BIT(31) /*!< DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ +#define ENET_TDES1_TB1S BITS(0,12) /*!< transmit buffer 1 size */ +#define ENET_TDES1_TB2S BITS(16,28) /*!< transmit buffer 2 size */ + +/* ENET DMA Tx descriptor TDES2 */ +#define ENET_TDES2_TB1AP BITS(0,31) /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES3 */ +#define ENET_TDES3_TB2AP BITS(0,31) /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/* ENET DMA Tx descriptor TDES6 */ +#define ENET_TDES6_TTSL BITS(0,31) /*!< transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES7 */ +#define ENET_TDES7_TTSH BITS(0,31) /*!< transmit frame timestamp high 32-bit value */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* ENET DMA Rx descriptor RDES0 */ +#define ENET_RDES0_PCERR BIT(0) /*!< payload checksum error */ +#define ENET_RDES0_EXSV BIT(0) /*!< extended status valid */ +#define ENET_RDES0_CERR BIT(1) /*!< CRC error */ +#define ENET_RDES0_DBERR BIT(2) /*!< dribble bit error */ +#define ENET_RDES0_RERR BIT(3) /*!< receive error */ +#define ENET_RDES0_RWDT BIT(4) /*!< receive watchdog timeout */ +#define ENET_RDES0_FRMT BIT(5) /*!< frame type */ +#define ENET_RDES0_LCO BIT(6) /*!< late collision */ +#define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ +#define ENET_RDES0_TSV BIT(7) /*!< timestamp valid */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ +#define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ +#define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ +#define ENET_RDES0_LERR BIT(12) /*!< length error */ +#define ENET_RDES0_SAFF BIT(13) /*!< SA filter fail */ +#define ENET_RDES0_DERR BIT(14) /*!< descriptor error */ +#define ENET_RDES0_ERRS BIT(15) /*!< error summary */ +#define ENET_RDES0_FRML BITS(16,29) /*!< frame length */ +#define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ +#define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ +#define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ +#define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ +#define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ +#define ENET_RDES1_RB2S BITS(16,28) /*!< receive buffer 2 size */ +#define ENET_RDES1_DINTC BIT(31) /*!< disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 */ +#define ENET_RDES2_RB1AP BITS(0,31) /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */ + +/* ENET DMA Rx descriptor RDES3 */ +#define ENET_RDES3_RB2AP BITS(0,31) /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/* ENET DMA Rx descriptor RDES4 */ +#define ENET_RDES4_IPPLDT BITS(0,2) /*!< IP frame payload type */ +#define ENET_RDES4_IPHERR BIT(3) /*!< IP frame header error */ +#define ENET_RDES4_IPPLDERR BIT(4) /*!< IP frame payload error */ +#define ENET_RDES4_IPCKSB BIT(5) /*!< IP frame checksum bypassed */ +#define ENET_RDES4_IPF4 BIT(6) /*!< IP frame in version 4 */ +#define ENET_RDES4_IPF6 BIT(7) /*!< IP frame in version 6 */ +#define ENET_RDES4_PTPMT BITS(8,11) /*!< PTP message type */ +#define ENET_RDES4_PTPOEF BIT(12) /*!< PTP on ethernet frame */ +#define ENET_RDES4_PTPVF BIT(13) /*!< PTP version format */ + +/* ENET DMA Rx descriptor RDES6 */ +#define ENET_RDES6_RTSL BITS(0,31) /*!< receive frame timestamp low 32-bit value */ + +/* ENET DMA Rx descriptor RDES7 */ +#define ENET_RDES7_RTSH BITS(0,31) /*!< receive frame timestamp high 32-bit value */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* constants definitions */ +/* define bit position and its register index offset */ +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* ENET clock range judgement */ +#define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) + +/* define MAC address configuration and reference address */ +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x40U) +#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) + +/* register offset */ +#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ + +#define PTP_TSF_REG_OFFSET 0x0728U /*!< PTP time stamp flag register offset */ + +#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ + +/* ENET status flag get */ +typedef enum +{ + /* ENET_MAC_WUM register */ + ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + /* ENET_MAC_FCTL register */ + ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ + /* ENET_MAC_INTF register */ + ENET_MAC_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_PTP_TSF register */ + ENET_PTP_FLAG_TSSCO = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 0U), /*!< timestamp second counter overflow flag */ + ENET_PTP_FLAG_TTM = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 1U), /*!< target time match flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_EB_DMA_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U), /*!< error during data transfer by RxDMA/TxDMA flag */ + ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U), /*!< error during write/read transfer flag */ + ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ + ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_flag_enum; + +/* ENET stutus flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_flag_clear_enum; + +/* ENET interrupt enable/disable */ +typedef enum +{ + /* ENET_MAC_INTMSK register */ + ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ + ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ + /* ENET_MSC_RINTMSK register */ + ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ + ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ + ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ + /* ENET_MSC_TINTMSK register */ + ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ + ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ + ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ + /* ENET_DMA_INTEN register */ + ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ + ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ + ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ + ENET_DMA_INT_TJTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U), /*!< transmit jabber timeout interrupt enable */ + ENET_DMA_INT_ROIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U), /*!< receive overflow interrupt enable */ + ENET_DMA_INT_TUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U), /*!< transmit underflow interrupt enable */ + ENET_DMA_INT_RIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U), /*!< receive interrupt enable */ + ENET_DMA_INT_RBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U), /*!< receive buffer unavailable interrupt enable */ + ENET_DMA_INT_RPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U), /*!< receive process stopped interrupt enable */ + ENET_DMA_INT_RWTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U), /*!< receive watchdog timeout interrupt enable */ + ENET_DMA_INT_ETIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U), /*!< early transmit interrupt enable */ + ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ + ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ + ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ +}enet_int_enum; + +/* ENET interrupt flag get */ +typedef enum +{ + /* ENET_MAC_INTF register */ + ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_INT_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_INT_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_INT_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_INT_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_INT_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_INT_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_INT_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_INT_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_INT_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_int_flag_enum; + +/* ENET interrupt flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_int_flag_clear_enum; + +/* current RX/TX descriptor/buffer/descriptor table address get */ +typedef enum +{ + ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ + ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ + ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ + ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ + ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ + ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ +}enet_desc_reg_enum; + +/* MAC statistics counter get */ +typedef enum +{ + ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ + ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ + ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ + ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ + ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ + ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ +}enet_msc_counter_enum; + +/* function option, used for ENET initialization */ +typedef enum +{ + FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ + DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ + DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ + DMA_ARBITRATION_OPTION = BIT(3), /*!< configure the DMA arbitration related parameters */ + STORE_OPTION = BIT(4), /*!< configure the store forward mode related parameters */ + DMA_OPTION = BIT(5), /*!< configure the DMA control related parameters */ + VLAN_OPTION = BIT(6), /*!< configure the VLAN tag related parameters */ + FLOWCTL_OPTION = BIT(7), /*!< configure the flow control related parameters */ + HASHH_OPTION = BIT(8), /*!< configure the hash list high 32-bit related parameters */ + HASHL_OPTION = BIT(9), /*!< configure the hash list low 32-bit related parameters */ + FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ + HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ + TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ + INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ +}enet_option_enum; + +/* phy mode and mac loopback configurations */ +typedef enum +{ + ENET_AUTO_NEGOTIATION = 0x01u, /*!< PHY auto negotiation */ + ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ + ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ + ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ +}enet_mediamode_enum; + +/* IP frame checksum function */ +typedef enum +{ + ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ + ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped */ +}enet_chksumconf_enum; + +/* received frame filter function */ +typedef enum +{ + ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ + ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ + ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ + ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ +}enet_frmrecept_enum; + +/* register group value get */ +typedef enum +{ + ALL_MAC_REG = 0, /*!< MAC register group */ + ALL_MSC_REG = 22, /*!< MSC register group */ + ALL_PTP_REG = 33, /*!< PTP register group */ + ALL_DMA_REG = 44, /*!< DMA register group */ +}enet_registers_type_enum; + +/* dma direction select */ +typedef enum +{ + ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ + ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ +}enet_dmadirection_enum; + +/* PHY operation direction select */ +typedef enum +{ + ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ + ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ +}enet_phydirection_enum; + +/* register operation direction select */ +typedef enum +{ + ENET_REG_READ, /*!< read register */ + ENET_REG_WRITE /*!< write register */ +}enet_regdirection_enum; + +/* ENET MAC addresses */ +typedef enum +{ + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ +}enet_macaddress_enum; + +/* descriptor information */ +typedef enum +{ + TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ + TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ + RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ + RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ + RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ + RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ +}enet_descstate_enum; + +/* MSC counters preset mode */ +typedef enum +{ + ENET_MSC_PRESET_NONE = 0U, /*!< do not preset MSC counter */ + ENET_MSC_PRESET_HALF = ENET_MSC_CTL_PMC, /*!< preset all MSC counters to almost-half(0x7FFF FFF0) value */ + ENET_MSC_PRESET_FULL = ENET_MSC_CTL_PMC | ENET_MSC_CTL_AFHPM /*!< preset all MSC counters to almost-full(0xFFFF FFF0) value */ +}enet_msc_preset_enum; + +/* structure for initialization of the ENET */ +typedef struct +{ + uint32_t option_enable; /*!< select which function to configure */ + uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ + uint32_t dma_maxburst; /*!< DMA max burst related parameters */ + uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ + uint32_t store_forward_mode; /*!< store forward mode related parameters */ + uint32_t dma_function; /*!< DMA control related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t flow_control; /*!< flow control related parameters */ + uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ + uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ + uint32_t framesfilter_mode; /*!< frame filter control related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t timer_config; /*!< frame timer related parameters */ + uint32_t interframegap; /*!< inter frame gap related parameters */ +}enet_initpara_struct; + +/* structure for ENET DMA desciptors */ +typedef struct +{ + uint32_t status; /*!< status */ + uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ + uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ + uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + uint32_t extended_status; /*!< extended status */ + uint32_t reserved; /*!< reserved */ + uint32_t timestamp_low; /*!< timestamp low */ + uint32_t timestamp_high; /*!< timestamp high */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +} enet_descriptors_struct; + +/* structure of PTP system time */ +typedef struct +{ + uint32_t second; /*!< second of system time */ + uint32_t nanosecond; /*!< nanosecond of system time */ + uint32_t sign; /*!< sign of system time */ +}enet_ptp_systime_struct; + +/* mac_cfg register value */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ + +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ +#define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ +#define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ +#define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ + +#define ENET_TYPEFRAME_CRC_DROP_ENABLE ENET_MAC_CFG_TFCD /*!< FCS field(last 4 bytes) of frame will be dropped before forwarding */ +#define ENET_TYPEFRAME_CRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< FCS field(last 4 bytes) of frame will not be dropped before forwarding */ +#define ENET_TYPEFRAME_CRC_DROP ENET_MAC_CFG_TFCD /*!< the function that FCS field(last 4 bytes) of frame will be dropped before forwarding */ + +#define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ +#define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ + +#define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ +#define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ + +#define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ +#define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ + +#define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ +#define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ + +#define ENET_RECEIVEOWN_ENABLE ((uint32_t)0x00000000U) /*!< the MAC receives all packets that are given by the PHY while transmitting */ +#define ENET_RECEIVEOWN_DISABLE ENET_MAC_CFG_ROD /*!< the MAC disables the reception of frames in half-duplex mode */ + +#define ENET_LOOPBACKMODE_ENABLE ENET_MAC_CFG_LBM /*!< the MAC operates in loopback mode at the MII */ +#define ENET_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000U) /*!< the MAC operates in normal mode */ + +#define ENET_MODE_FULLDUPLEX ENET_MAC_CFG_DPM /*!< full-duplex mode enable */ +#define ENET_MODE_HALFDUPLEX ((uint32_t)0x00000000U) /*!< half-duplex mode enable */ + +#define ENET_CHECKSUMOFFLOAD_ENABLE ENET_MAC_CFG_IPFCO /*!< IP frame checksum offload function enabled for received IP frame */ +#define ENET_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000U) /*!< the checksum offload function in the receiver is disabled */ + +#define ENET_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000U) /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/ +#define ENET_RETRYTRANSMISSION_DISABLE ENET_MAC_CFG_RTD /*!< the MAC attempts only 1 transmission */ + +#define ENET_AUTO_PADCRC_DROP_ENABLE ENET_MAC_CFG_APCD /*!< the MAC strips the Pad/FCS field on received frames */ +#define ENET_AUTO_PADCRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< the MAC forwards all received frames without modify it */ +#define ENET_AUTO_PADCRC_DROP ENET_MAC_CFG_APCD /*!< the function of the MAC strips the Pad/FCS field on received frames */ + +#define ENET_DEFERRALCHECK_ENABLE ENET_MAC_CFG_DFC /*!< the deferral check function is enabled in the MAC */ +#define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ + +/* mac_frmf register value */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ +#define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ +#define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ + +#define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ +#define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ + +#define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ +#define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ +#define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ +#define ENET_SRC_FILTER ENET_MAC_FRMF_SAFLT /*!< filter source address function */ +#define ENET_SRC_FILTER_INVERSE ENET_MAC_FRMF_SAIFLT /*!< inverse source address filtering result function */ + +#define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ +#define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ + +#define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ + +#define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ +#define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ + +#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ +#define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ +#define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ +#define ENET_MULTICAST_FILTER_NONE ENET_MAC_FRMF_MFD /*!< all multicast frames are passed */ +#define ENET_MULTICAST_FILTER_PASS ENET_MAC_FRMF_MFD /*!< pass all multicast frames function */ +#define ENET_MULTICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HMF /*!< HASH multicast filter function */ +#define ENET_FILTER_MODE_EITHER ENET_MAC_FRMF_HPFLT /*!< HASH or perfect filter function */ + +#define ENET_UNICAST_FILTER_EITHER (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT) /*!< pass unicast frames that match either the perfect or the hash filtering */ +#define ENET_UNICAST_FILTER_HASH ENET_MAC_FRMF_HUF /*!< pass unicast frames that match the hash filtering */ +#define ENET_UNICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass unicast frames that match the perfect filtering */ +#define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ + +/* mac_phy_ctl register value */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ + +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ + +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ + +/* mac_phy_data register value */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ + +/* mac_fctl register value */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ + +#define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE ENET_MAC_FCTL_DZQP /*!< the automatic zero-quanta generation function */ + +#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ +#define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ + +#define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ +#define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ +#define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ + +#define ENET_TX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_TFCEN /*!< enable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< disable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL ENET_MAC_FCTL_TFCEN /*!< the flow control operation in the MAC */ + +#define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ +/* mac_vlt register value */ +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + +#define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ +#define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ + +/* mac_wum register value */ +#define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ +#define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ +#define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + +/* mac_dbg register value */ +#define ENET_MAC_RECEIVER_NOT_IDLE ENET_MAC_DBG_MRNI /*!< MAC receiver is not in idle state */ +#define ENET_RX_ASYNCHRONOUS_FIFO_STATE ENET_MAC_DBG_RXAFS /*!< Rx asynchronous FIFO status */ +#define ENET_RXFIFO_WRITING ENET_MAC_DBG_RXFW /*!< RxFIFO is doing write operation */ +#define ENET_RXFIFO_READ_STATUS ENET_MAC_DBG_RXFRS /*!< RxFIFO read operation status */ +#define ENET_RXFIFO_STATE ENET_MAC_DBG_RXFS /*!< RxFIFO state */ +#define ENET_MAC_TRANSMITTER_NOT_IDLE ENET_MAC_DBG_MTNI /*!< MAC transmitter is not in idle state */ +#define ENET_MAC_TRANSMITTER_STATUS ENET_MAC_DBG_SOMT /*!< status of MAC transmitter */ +#define ENET_PAUSE_CONDITION_STATUS ENET_MAC_DBG_PCS /*!< pause condition status */ +#define ENET_TXFIFO_READ_STATUS ENET_MAC_DBG_TXFRS /*!< TxFIFO read operation status */ +#define ENET_TXFIFO_WRITING ENET_MAC_DBG_TXFW /*!< TxFIFO is doing write operation */ +#define ENET_TXFIFO_NOT_EMPTY ENET_MAC_DBG_TXFNE /*!< TxFIFO is not empty */ +#define ENET_TXFIFO_FULL ENET_MAC_DBG_TXFF /*!< TxFIFO is full */ + +#define GET_MAC_DBG_RXAFS(regval) GET_BITS((regval),1,2) /*!< get value of ENET_MAC_DBG_RXAFS bit field */ + +#define GET_MAC_DBG_RXFRS(regval) GET_BITS((regval),5,6) /*!< get value of ENET_MAC_DBG_RXFRS bit field */ + +#define GET_MAC_DBG_RXFS(regval) GET_BITS((regval),8,9) /*!< get value of ENET_MAC_DBG_RXFS bit field */ + +#define GET_MAC_DBG_SOMT(regval) GET_BITS((regval),17,18) /*!< get value of ENET_MAC_DBG_SOMT bit field */ + +#define GET_MAC_DBG_TXFRS(regval) GET_BITS((regval),20,21) /*!< get value of ENET_MAC_DBG_TXFRS bit field */ + +/* mac_addr0h register value */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ + +/* mac_addrxh register value, x = 1,2,3 */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ + +#define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ +#define ENET_ADDRESS_MASK_BYTE2 BIT(26) /*!< low register bits [23:16] */ +#define ENET_ADDRESS_MASK_BYTE3 BIT(27) /*!< low register bits [31:24] */ +#define ENET_ADDRESS_MASK_BYTE4 BIT(28) /*!< high register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ + +#define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + +/* mac_fcth register value */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0)) << 8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ +#define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ +#define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ +#define ENET_ACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFA(3) /*!< threshold level is 1024 bytes */ +#define ENET_ACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFA(4) /*!< threshold level is 1280 bytes */ +#define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ +#define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ + +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4)) << 8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ +#define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ +#define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFD(3) /*!< threshold level is 1024 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFD(4) /*!< threshold level is 1280 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFD(5) /*!< threshold level is 1536 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFD(6) /*!< threshold level is 1792 bytes */ + +/* msc_ctl register value */ +#define ENET_MSC_COUNTER_STOP_ROLLOVER ENET_MSC_CTL_CTSR /*!< counter stop rollover */ +#define ENET_MSC_RESET_ON_READ ENET_MSC_CTL_RTOR /*!< reset on read */ +#define ENET_MSC_COUNTERS_FREEZE ENET_MSC_CTL_MCFZ /*!< MSC counter freeze */ + +/* ptp_tsctl register value */ +#define PTP_TSCTL_CKNT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_PTP_TSCTL_CKNT bit field */ + +#define ENET_RXTX_TIMESTAMP ENET_PTP_TSCTL_TMSEN /*!< enable timestamp function for transmit and receive frames */ +#define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ +#define ENET_ALL_RX_TIMESTAMP ENET_PTP_TSCTL_ARFSEN /*!< all received frames are taken snapshot */ +#define ENET_NONTYPE_FRAME_SNAPSHOT ENET_PTP_TSCTL_ESEN /*!< take snapshot when received non type frame */ +#define ENET_IPV6_FRAME_SNAPSHOT ENET_PTP_TSCTL_IP6SEN /*!< take snapshot for IPv6 frame */ +#define ENET_IPV4_FRAME_SNAPSHOT ENET_PTP_TSCTL_IP4SEN /*!< take snapshot for IPv4 frame */ +#define ENET_PTP_FRAME_USE_MACADDRESS_FILTER ENET_PTP_TSCTL_MAFEN /*!< enable MAC address1-3 to filter the PTP frame */ + +/* ptp_ssinc register value */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ + +/* ptp_tsl register value */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ + +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ + +/* ptp_tsul register value */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ + +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ + +/* ptp_ppsctl register value */ +#define PTP_PPSCTL_PPSOFC(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_PPSCTL_PPSOFC bit field */ +#define ENET_PPSOFC_1HZ PTP_PPSCTL_PPSOFC(0) /*!< PPS output 1Hz frequency */ +#define ENET_PPSOFC_2HZ PTP_PPSCTL_PPSOFC(1) /*!< PPS output 2Hz frequency */ +#define ENET_PPSOFC_4HZ PTP_PPSCTL_PPSOFC(2) /*!< PPS output 4Hz frequency */ +#define ENET_PPSOFC_8HZ PTP_PPSCTL_PPSOFC(3) /*!< PPS output 8Hz frequency */ +#define ENET_PPSOFC_16HZ PTP_PPSCTL_PPSOFC(4) /*!< PPS output 16Hz frequency */ +#define ENET_PPSOFC_32HZ PTP_PPSCTL_PPSOFC(5) /*!< PPS output 32Hz frequency */ +#define ENET_PPSOFC_64HZ PTP_PPSCTL_PPSOFC(6) /*!< PPS output 64Hz frequency */ +#define ENET_PPSOFC_128HZ PTP_PPSCTL_PPSOFC(7) /*!< PPS output 128Hz frequency */ +#define ENET_PPSOFC_256HZ PTP_PPSCTL_PPSOFC(8) /*!< PPS output 256Hz frequency */ +#define ENET_PPSOFC_512HZ PTP_PPSCTL_PPSOFC(9) /*!< PPS output 512Hz frequency */ +#define ENET_PPSOFC_1024HZ PTP_PPSCTL_PPSOFC(10) /*!< PPS output 1024Hz frequency */ +#define ENET_PPSOFC_2048HZ PTP_PPSCTL_PPSOFC(11) /*!< PPS output 2048Hz frequency */ +#define ENET_PPSOFC_4096HZ PTP_PPSCTL_PPSOFC(12) /*!< PPS output 4096Hz frequency */ +#define ENET_PPSOFC_8192HZ PTP_PPSCTL_PPSOFC(13) /*!< PPS output 8192Hz frequency */ +#define ENET_PPSOFC_16384HZ PTP_PPSCTL_PPSOFC(14) /*!< PPS output 16384Hz frequency */ +#define ENET_PPSOFC_32768HZ PTP_PPSCTL_PPSOFC(15) /*!< PPS output 32768Hz frequency */ + +/* dma_bctl register value */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define ENET_ENHANCED_DESCRIPTOR ENET_DMA_BCTL_DFM /*!< enhanced mode descriptor */ +#define ENET_NORMAL_DESCRIPTOR ((uint32_t)0x00000000) /*!< normal mode descriptor */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ + +#define ENET_MIXED_BURST_ENABLE ENET_DMA_BCTL_MB /*!< AHB master interface transfer burst length greater than 16 with INCR */ +#define ENET_MIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB master interface only transfer fixed burst length with 16 and below */ + +/* dma_stat register value */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ +#define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ + +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ +#define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ + +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ + +/* dma_ctl register value */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ + +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES DMA_CTL_TTHC(3) /*!< threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES DMA_CTL_TTHC(4) /*!< threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES DMA_CTL_TTHC(5) /*!< threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES DMA_CTL_TTHC(6) /*!< threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ + +#define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ + +#define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ + +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ + +#define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ + +#define ENET_FORWARD_ERRFRAMES_ENABLE (ENET_DMA_CTL_FERF << 2) /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF << 2) /*!< the function that all frame received with error except runt error are forwarded to memory */ + +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF << 2) /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF << 2) /*!< the function that forwarding undersized good frames */ + +#define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ + +/* dma_mfbocnt register value */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ + +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ + +/* dma_rswdc register value */ +#define DMA_RSWDC_WDCFRS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_DMA_RSWDC_WDCFRS bit field */ + +/* dma tx descriptor tdes0 register value */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ + +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ + +/* dma tx descriptor tdes1 register value */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ + +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ + +/* dma rx descriptor rdes0 register value */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ + +/* dma rx descriptor rdes1 register value */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ + +#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ + +#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ + +/* dma rx descriptor rdes4 register value */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ + +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ + +/* ENET register mask value */ +#define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ +#define MAC_FCTL_MASK ((uint32_t)0x0000FF41U) /*!< ENET_MAC_FCTL register mask */ +#define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ +#define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ +#define ENET_MSC_PRESET_MASK (~(ENET_MSC_CTL_PMC | ENET_MSC_CTL_AFHPM)) /*!< ENET_MSC_CTL preset mask */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +#define ETH_DMATXDESC_SIZE 0x20U /*!< TxDMA enhanced descriptor size */ +#define ETH_DMARXDESC_SIZE 0x20U /*!< RxDMA enhanced descriptor size */ +#else +#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + + +typedef enum{ + ENET_CKNT_ORDINARY = PTP_TSCTL_CKNT(0), /*!< type of ordinary clock node type for timestamp */ + ENET_CKNT_BOUNDARY = PTP_TSCTL_CKNT(1), /*!< type of boundary clock node type for timestamp */ + ENET_CKNT_END_TO_END = PTP_TSCTL_CKNT(2), /*!< type of end-to-end transparent clock node type for timestamp */ + ENET_CKNT_PEER_TO_PEER = PTP_TSCTL_CKNT(3), /*!< type of peer-to-peer transparent clock node type for timestamp */ + ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ + ENET_SUBSECOND_DIGITAL_ROLLOVER = (int32_t)(ENET_PTP_TSCTL_SCROM | BIT(31)), /*!< digital rollover mode */ + ENET_SUBSECOND_BINARY_ROLLOVER = ENET_PTP_TSCTL_SCROM, /*!< binary rollover mode */ + ENET_SNOOPING_PTP_VERSION_2 = (int32_t)(ENET_PTP_TSCTL_PFSV| BIT(31)), /*!< version 2 */ + ENET_SNOOPING_PTP_VERSION_1 = ENET_PTP_TSCTL_PFSV, /*!< version 1 */ + ENET_EVENT_TYPE_MESSAGES_SNAPSHOT = (int32_t)(ENET_PTP_TSCTL_ETMSEN| BIT(31)), /*!< only event type messages are taken snapshot */ + ENET_ALL_TYPE_MESSAGES_SNAPSHOT = ENET_PTP_TSCTL_ETMSEN, /*!< all type messages are taken snapshot except announce, management and signaling message */ + ENET_MASTER_NODE_MESSAGE_SNAPSHOT = (int32_t)(ENET_PTP_TSCTL_MNMSEN| BIT(31)), /*!< snapshot is only take for master node message */ + ENET_SLAVE_NODE_MESSAGE_SNAPSHOT = ENET_PTP_TSCTL_MNMSEN, /*!< snapshot is only taken for slave node message */ +}enet_ptp_function_enum; + + +/* ENET remote wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ + +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ + +/* ENET delay timeout */ +#define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ +#define ENET_RESET_TO ((uint32_t)0x000004FFU) /*!< ENET reset timeout */ + + + +/* function declarations */ +/* main function */ +/* deinitialize the ENET, and reset structure parameters for ENET initialization */ +void enet_deinit(void); +/* configure the parameters which are usually less cared for initialization */ +void enet_initpara_config(enet_option_enum option, uint32_t para); +/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept); +/* reset all core internal registers located in CLK_TX and CLK_RX */ +ErrStatus enet_software_reset(void); +/* check receive frame valid and return frame size */ +uint32_t enet_rxframe_size_get(void); +/* initialize the dma tx/rx descriptors's parameters in chain mode */ +void enet_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma tx/rx descriptors's parameters in ring mode */ +void enet_descriptors_ring_init(enet_dmadirection_enum direction); +/* handle current received frame data to application buffer */ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize); +/* handle current received frame but without data copy to application buffer */ +#define ENET_NOCOPY_FRAME_RECEIVE() enet_frame_receive(NULL, 0U) +/* handle application buffer data to transmit it */ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); +/* handle current transmit frame but without data copy from application buffer */ +#define ENET_NOCOPY_FRAME_TRANSMIT(len) enet_frame_transmit(NULL, (len)) +/* configure the transmit IP frame checksum offload calculation and insertion */ +ErrStatus enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); +/* ENET Tx and Rx function enable (include MAC and DMA module) */ +void enet_enable(void); +/* ENET Tx and Rx function disable (include MAC and DMA module) */ +void enet_disable(void); +/* configure MAC address */ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); +/* get MAC address */ +ErrStatus enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[], uint8_t bufsize); + +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + +/* MAC function */ +/* ENET Tx function enable (include MAC and DMA module) */ +void enet_tx_enable(void); +/* ENET Tx function disable (include MAC and DMA module) */ +void enet_tx_disable(void); +/* ENET Rx function enable (include MAC and DMA module) */ +void enet_rx_enable(void); +/* ENET Rx function disable (include MAC and DMA module) */ +void enet_rx_disable(void); +/* put registers value into the application buffer */ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num); +/* get the enet debug status from the debug register */ +uint32_t enet_debug_status_get(uint32_t mac_debug); +/* enable the MAC address filter */ +void enet_address_filter_enable(enet_macaddress_enum mac_addr); +/* disable the MAC address filter */ +void enet_address_filter_disable(enet_macaddress_enum mac_addr); +/* configure the MAC address filter */ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type); +/* PHY interface configuration (configure SMI clock and reset PHY chip) */ +ErrStatus enet_phy_config(void); +/* write to/read from a PHY register */ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue); +/* enable the loopback function of phy chip */ +ErrStatus enet_phyloopback_enable(void); +/* disable the loopback function of phy chip */ +ErrStatus enet_phyloopback_disable(void); +/* enable ENET forward feature */ +void enet_forward_feature_enable(uint32_t feature); +/* disable ENET forward feature */ +void enet_forward_feature_disable(uint32_t feature); +/* enable ENET fliter feature */ +void enet_fliter_feature_enable(uint32_t feature); +/* disable ENET fliter feature */ +void enet_fliter_feature_disable(uint32_t feature); + +/* flow control function */ +/* generate the pause frame, ENET will send pause frame after enable transmit flow control */ +ErrStatus enet_pauseframe_generate(void); +/* configure the pause frame detect type */ +void enet_pauseframe_detect_config(uint32_t detect); +/* configure the pause frame parameters */ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold); +/* configure the threshold of the flow control(deactive and active threshold) */ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active); +/* enable ENET flow control feature */ +void enet_flowcontrol_feature_enable(uint32_t feature); +/* disable ENET flow control feature */ +void enet_flowcontrol_feature_disable(uint32_t feature); + +/* DMA function */ +/* get the dma transmit/receive process state */ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +/* poll the dma transmission/reception enable */ +void enet_dmaprocess_resume(enet_dmadirection_enum direction); +/* check and recover the Rx process */ +void enet_rxprocess_check_recovery(void); +/* flush the ENET transmit fifo, and wait until the flush operation completes */ +ErrStatus enet_txfifo_flush(void); +/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get); +/* get the Tx or Rx descriptor information */ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get); +/* get the number of missed frames during receiving */ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop); + +/* descriptor function */ +/* get the bit flag of ENET dma descriptor */ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag); +/* set the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); +/* clear the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will immediately set */ +void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct *desc); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time */ +void enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct *desc, uint32_t delay_time); +/* drop current receive frame */ +void enet_rxframe_drop(void); +/* enable DMA feature */ +void enet_dma_feature_enable(uint32_t feature); +/* disable DMA feature */ +void enet_dma_feature_disable(uint32_t feature); + + +/* special enhanced mode function */ +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/* get the bit of extended status flag in ENET DMA descriptor */ +uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_t desc_status); +/* configure descriptor to work in enhanced mode */ +void enet_desc_select_enhanced_mode(void); +/* initialize the dma Tx/Rx descriptors's parameters in enhanced chain mode with ptp function */ +void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma Tx/Rx descriptors's parameters in enhanced ring mode with ptp function */ +void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction); +/* receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode */ +ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP enhanced mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(ptr) enet_ptpframe_receive_enhanced_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode */ +ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP enhanced mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(len, ptr) enet_ptpframe_transmit_enhanced_mode(NULL, (len), (ptr)) + +#else + +/* configure descriptor to work in normal mode */ +void enet_desc_select_normal_mode(void); +/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr) enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr) enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr)) + +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* WUM function */ +/* wakeup frame filter register pointer reset */ +void enet_wum_filter_register_pointer_reset(void); +/* set the remote wakeup frame registers */ +void enet_wum_filter_config(uint32_t pdata[]); +/* enable wakeup management features */ +void enet_wum_feature_enable(uint32_t feature); +/* disable wakeup management features */ +void enet_wum_feature_disable(uint32_t feature); + +/* MSC function */ +/* reset the MAC statistics counters */ +void enet_msc_counters_reset(void); +/* enable the MAC statistics counter features */ +void enet_msc_feature_enable(uint32_t feature); +/* disable the MAC statistics counter features */ +void enet_msc_feature_disable(uint32_t feature); +/* configure MAC statistics counters preset mode */ +void enet_msc_counters_preset_config(enet_msc_preset_enum mode); +/* get MAC statistics counter */ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); + +/* PTP function */ +/* change subsecond to nanosecond */ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond); +/* change nanosecond to subsecond */ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond); +/* enable the PTP features */ +void enet_ptp_feature_enable(uint32_t feature); +/* disable the PTP features */ +void enet_ptp_feature_disable(uint32_t feature); +/* configure the PTP timestamp function */ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func); +/* configure the PTP system time subsecond increment value */ +void enet_ptp_subsecond_increment_config(uint32_t subsecond); +/* adjusting the PTP clock frequency only in fine update mode */ +void enet_ptp_timestamp_addend_config(uint32_t add); +/* initializing or adding/subtracting to second of the PTP system time */ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond); +/* configure the PTP expected target time */ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond); +/* get the PTP current system time */ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct); +/* configure the PPS output frequency */ +void enet_ptp_pps_output_frequency_config(uint32_t freq); +/* configure and start PTP timestamp counter */ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg); +/* adjust frequency in fine method by configure addend register */ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); +/* update system time in coarse method */ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); +/* set system time in fine method */ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +/* get the ptp flag status */ +FlagStatus enet_ptp_flag_get(uint32_t flag); + +/* internal function */ +/* reset the ENET initpara struct, call it before using enet_initpara_config() */ +void enet_initpara_reset(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + +#endif /* GD32F30X_ENET_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h new file mode 100644 index 0000000000..96cac05fba --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h @@ -0,0 +1,446 @@ +/*! + \file gd32f30x_exmc.h + \brief definitions for the EXMC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_EXMC_H +#define GD32F30X_EXMC_H + +#include "gd32f30x.h" + +/* EXMC definitions */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ + +/* registers definitions */ +/* NOR/PSRAM */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register0 */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register0 */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register0 */ + +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register1 */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register1 */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register1 */ + +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register2 */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register2 */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register2 */ + +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register3 */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register3 */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register3 */ + +/* NAND/PC card */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register1 */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register1 */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register1 */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register1 */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register1 */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register2 */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register2 */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register2 */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register2 */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register2 */ + +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register3 */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register3 */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register3 */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register3 */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ + +/* bits definitions */ +/* EXMC_SNCTLx,x=0..3 */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing enable */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait enable */ +#define EXMC_SNCTL_CPS BITS(16,18) /*!< CRAM page size */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write config */ + +/* EXMC_SNTCFGx,x=0..3 */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< asynchronous address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< asynchronous address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< asynchronous data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< synchronous data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_SNWTCFGx,x=0..3 */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< asynchronous address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< asynchronous address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< asynchronous data setup time */ +#define EXMC_SNWTCFG_WBUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_NPCTLx,x=1..3 */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ + +/* EXMC_NPINTENx,x=1..3 */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ + +/* EXMC_NPCTCFGx,x=1..3 */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ + +/* EXMC_NPATCFGx,x=1..3 */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ + +/* EXMC_PIOTCFG3 */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ + +/* EXMC_NECCx,x=1,2 */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ + +/* constants definitions */ +/* EXMC NOR/SRAM timing initialize struct */ +typedef struct +{ + uint32_t asyn_access_mode; /*!< asynchronous access mode */ + uint32_t syn_data_latency; /*!< configure the data latency */ + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ + uint32_t bus_latency; /*!< configure the bus latency */ + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ +}exmc_norsram_timing_parameter_struct; + +/* EXMC NOR/SRAM initialize struct */ +typedef struct +{ + uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ + uint32_t extended_mode; /*!< enable or disable the extended mode */ + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ + uint32_t memory_write; /*!< enable or disable the write operation */ + uint32_t nwait_config; /*!< NWAIT signal configuration */ + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ + uint32_t burst_mode; /*!< enable or disable the burst mode */ + uint32_t databus_width; /*!< specifies the databus width of external memory */ + uint32_t memory_type; /*!< specifies the type of external memory */ + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extended mode is not used or the timing + parameters for read if the extended mode is used */ + exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extended mode is used */ +}exmc_norsram_parameter_struct; + +/* EXMC NAND/PC card timing initialize struct */ +typedef struct +{ + uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ + uint32_t waittime; /*!< configure the minimum wait time */ + uint32_t setuptime; /*!< configure the address setup time */ +}exmc_nand_pccard_timing_parameter_struct; + +/* EXMC NAND initialize struct */ +typedef struct +{ + uint32_t nand_bank; /*!< select the bank of NAND */ + uint32_t ecc_size; /*!< the page size for the ECC calculation */ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ + uint32_t databus_width; /*!< the NAND flash databus width */ + uint32_t wait_feature; /*!< enable or disable the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ +}exmc_nand_parameter_struct; + +/* EXMC PC card initialize struct */ +typedef struct +{ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t wait_feature; /*!< enable or disable the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for PC card common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for PC card attribute space */ + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for PC card IO space */ +}exmc_pccard_parameter_struct; + +/* EXMC_register address */ +#define EXMC_SNCTL(region) REG32(EXMC + 0x08U * (region)) /*!< EXMC SRAM/NOR flash control registers, region = 0,1,2,3 */ +#define EXMC_SNTCFG(region) REG32(EXMC + 0x04U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash timing configuration registers, region = 0,1,2,3 */ +#define EXMC_SNWTCFG(region) REG32(EXMC + 0x104U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash write timing configuration registers, region = 0,1,2,3 */ + +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U * (bank)) /*!< EXMC NAND/PC card control registers, bank = 1,2,3 */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U * (bank)) /*!< EXMC NAND/PC card interrupt enable registers, bank = 1,2,3 */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U * (bank)) /*!< EXMC NAND/PC card common space timing configuration registers, bank = 1,2,3 */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U * (bank)) /*!< EXMC NAND/PC card attribute space timing configuration registers, bank = 1,2,3 */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U * (bank)) /*!< EXMC NAND ECC registers, bank = 1,2 */ + +/* CRAM page size */ +#define SNCTL_CPS(regval) (BITS(16,18) & ((uint32_t)(regval) << 16)) +#define EXMC_CRAM_AUTO_SPLIT SNCTL_CPS(0) /*!< automatic burst split on page boundary crossing */ +#define EXMC_CRAM_PAGE_SIZE_128_BYTES SNCTL_CPS(1) /*!< page size is 128 bytes */ +#define EXMC_CRAM_PAGE_SIZE_256_BYTES SNCTL_CPS(2) /*!< page size is 256 bytes */ +#define EXMC_CRAM_PAGE_SIZE_512_BYTES SNCTL_CPS(3) /*!< page size is 512 bytes */ +#define EXMC_CRAM_PAGE_SIZE_1024_BYTES SNCTL_CPS(4) /*!< page size is 1024 bytes */ + +/* NOR bank memory data bus width */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width is 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width is 16 bits */ + +/* NOR bank memory type */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ + +/* asynchronous access mode */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ + +/* data latency for NOR flash */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency of first burst access is 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency of first burst access is 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency of first burst access is 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency of first burst access is 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency of first burst access is 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency of first burst access is 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency of first burst access is 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency of first burst access is 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency of first burst access is 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency of first burst access is 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency of first burst access is 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency of first burst access is 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency of first burst access is 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency of first burst access is 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency of first burst access is 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency of first burst access is 17 EXMC_CLK */ + +/* synchronous clock divide ratio */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_DISABLE SNTCFG_CKDIV(0) /*!< EXMC_CLK disable */ +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ + +/* ECC size */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* ECC size is 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* ECC size is 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* ECC size is 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* ECC size is 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* ECC size is 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* ECC size is 8192 bytes */ + +/* ALE to RE delay */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ + +/* CLE to RE delay */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ + +/* NAND bank memory data bus width */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width is 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width is 16 bits */ + +/* EXMC NOR/SRAM bank region definition */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ + +/* EXMC NOR/SRAM write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE EXMC_SNCTL_SYNCWR /*!< synchronous write mode */ + +/* EXMC NWAIT signal configuration */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING EXMC_SNCTL_NRWTCFG /*!< NWAIT signal is active during wait state */ + +/* EXMC NWAIT signal polarity configuration */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH EXMC_SNCTL_NRWTPOL /*!< high level is active of NWAIT */ + +/* EXMC NAND/PC card bank definition */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ + +/* EXMC flag bits */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ + +/* EXMC interrupt flag bits */ +#define EXMC_NAND_PCCARD_INT_FLAG_RISE EXMC_NPINTEN_INTREN /*!< rising edge interrupt and flag */ +#define EXMC_NAND_PCCARD_INT_FLAG_LEVEL EXMC_NPINTEN_INTHEN /*!< high-level interrupt and flag */ +#define EXMC_NAND_PCCARD_INT_FLAG_FALL EXMC_NPINTEN_INTFEN /*!< falling edge interrupt and flag */ + +/* function declarations */ +/* initialization functions */ +/* NOR/SRAM */ +/* deinitialize EXMC NOR/SRAM region */ +void exmc_norsram_deinit(uint32_t exmc_norsram_region); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize EXMC NOR/SRAM region */ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* enable EXMC NOR/SRAM region */ +void exmc_norsram_enable(uint32_t exmc_norsram_region); +/* disable EXMC NOR/SRAM region */ +void exmc_norsram_disable(uint32_t exmc_norsram_region); +/* NAND */ +/* deinitialize EXMC NAND bank */ +void exmc_nand_deinit(uint32_t exmc_nand_bank); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* initialize EXMC NAND bank */ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* enable EXMC NAND bank */ +void exmc_nand_enable(uint32_t exmc_nand_bank); +/* disable EXMC NAND bank */ +void exmc_nand_disable(uint32_t exmc_nand_bank); +/* PC card */ +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize exmc_pccard_parameter_struct parameter with the default values */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* enable EXMC PC card bank */ +void exmc_pccard_enable(void); +/* disable EXMC PC card bank */ +void exmc_pccard_disable(void); + +/* function configuration */ +/* NOR/SRAM */ +/* configure CRAM page size */ +void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size); +/* NAND */ +/* enable or disable the EXMC NAND ECC function */ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue); +/* get the EXMC ECC value */ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank); + +/* interrupt & flag functions */ +/* enable EXMC interrupt */ +void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt); +/* disable EXMC interrupt */ +void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt); +/* get EXMC flag status */ +FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag); +/* clear EXMC flag status */ +void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag); +/* get EXMC interrupt flag */ +FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt); +/* clear EXMC interrupt flag */ +void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt); + +#endif /* GD32F30X_EXMC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h new file mode 100644 index 0000000000..36a1098968 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h @@ -0,0 +1,255 @@ +/*! + \file gd32f30x_exti.h + \brief definitions for the EXTI + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_EXTI_H +#define GD32F30X_EXTI_H + +#include "gd32f30x.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ +#define EXTI_INTEN_INTEN19 BIT(19) /*!< interrupt from line 19 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ +#define EXTI_EVEN_EVEN19 BIT(19) /*!< event from line 19 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ +#define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ +#define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ +#define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum +{ + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ + EXTI_19 = BIT(19), /*!< EXTI line 19 */ +}exti_line_enum; + +/* external interrupt and event */ +typedef enum +{ + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +}exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum +{ + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH /*!< EXTI rising and falling edge trigger */ +}exti_trig_type_enum; + +/* function declarations */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32F30X_EXTI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h new file mode 100644 index 0000000000..77a2997293 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h @@ -0,0 +1,375 @@ +/*! + \file gd32f30x_fmc.h + \brief definitions for the FMC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_FMC_H +#define GD32F30X_FMC_H + +#include "gd32f30x.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_DATA1 REG16((OB) + 0x04U) /*!< option byte data1 value*/ +#define OB_DATA2 REG16((OB) + 0x06U) /*!< option byte data2 value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0,2) /*!< wait state counter */ + +/* FMC_KEY0 */ +#define FMC_KEY0_KEY BITS(0,31) /*!< FMC_CTL0 unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0,31) /*!< option bytes unlock key bits */ + +/* FMC_STAT0 */ +#define FMC_STAT0_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT0_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT0_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT0_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL0 */ +#define FMC_CTL0_PG BIT(0) /*!< main flash program for bank0 command bit */ +#define FMC_CTL0_PER BIT(1) /*!< main flash page erase for bank0 command bit */ +#define FMC_CTL0_MER BIT(2) /*!< main flash mass erase for bank0 command bit */ +#define FMC_CTL0_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL0_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL0_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL0_LK BIT(7) /*!< FMC_CTL0 lock bit */ +#define FMC_CTL0_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL0_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR0 */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2,9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10,25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0,31) /*!< store WP of option bytes block after system reset */ + +/* FMC_KEY1 */ +#define FMC_KEY1_KEY BITS(0,31) /*!< FMC_CTL1 unlock key bits */ + +/* FMC_STAT1 */ +#define FMC_STAT1_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT1_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT1_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT1_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL1 */ +#define FMC_CTL1_PG BIT(0) /*!< main flash program for bank1 command bit */ +#define FMC_CTL1_PER BIT(1) /*!< main flash page erase for bank1 command bit */ +#define FMC_CTL1_MER BIT(2) /*!< main flash mass erase for bank1 command bit */ +#define FMC_CTL1_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL1_LK BIT(7) /*!< FMC_CTL1 lock bit */ +#define FMC_CTL1_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR1 */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ +#define FMC_WSEN_BPEN BIT(1) /*!< FMC bit program enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0,31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum +{ + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +}fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum +{ + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ +}fmc_int_enum; + +/* FMC flags */ +typedef enum +{ + FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ + FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ + FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ + FMC_FLAG_BANK0_END = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U), /*!< FMC bank0 end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ + FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ + FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ + FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ +}fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum +{ + FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ + FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ +}fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x0FFF0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* unlock the FMC bank0 operation */ +void fmc_bank0_unlock(void); +/* unlock the FMC bank1 operation */ +void fmc_bank1_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* lock the bank0 FMC operation */ +void fmc_bank0_lock(void); +/* lock the bank1 FMC operation */ +void fmc_bank1_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC erase whole bank0 */ +fmc_state_enum fmc_bank0_erase(void); +/* FMC erase whole bank1 */ +fmc_state_enum fmc_bank1_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); +/* FMC reprogram a word at the corresponding address without erasing */ +fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the option byte */ +fmc_state_enum ob_erase(void); +/* enable write protect */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure the option byte security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* write the FMC option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program option bytes data */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get the FMC option byte user */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get option byte security protection code value */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); +/* check FMC bank0 ready or not */ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + +#endif /* GD32F30X_FMC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h new file mode 100644 index 0000000000..0803cc01cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h @@ -0,0 +1,107 @@ +/*! + \file gd32f30x_fwdgt.h + \brief definitions for the FWDGT + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_FWDGT_H +#define GD32F30X_FWDGT_H + +#include "gd32f30x.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x04U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x08U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0,15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0,2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0,11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32F30X_FWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h new file mode 100644 index 0000000000..47ff29a083 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h @@ -0,0 +1,536 @@ +/*! + \file gd32f30x_gpio.h + \brief definitions for the GPIO + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_GPIO_H +#define GD32F30X_GPIO_H + +#include "gd32f30x.h" + +/* GPIOx(x=A,B,C,D,E,F,G) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) +#define GPIOF (GPIO_BASE + 0x00001400U) +#define GPIOG (GPIO_BASE + 0x00001800U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ +#define GPIOx_SPD(gpiox) REG32((gpiox) + 0x3CU) /*!< GPIO port bit speed register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ +#define AFIO_CPSCTL REG32(AFIO + 0x20U) /*!< IO compensation control register */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8,9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10,11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12,13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14,15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16,17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18,19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20,21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22,23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24,25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26,27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28,29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8,9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10,11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12,13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14,15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16,17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18,19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20,21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22,23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24,25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26,27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28,29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* GPIO_SPD */ +#define GPIO_SPD_SPD0 BIT(0) /*!< pin 0 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD1 BIT(1) /*!< pin 1 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD2 BIT(2) /*!< pin 2 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD3 BIT(3) /*!< pin 3 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD4 BIT(4) /*!< pin 4 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD5 BIT(5) /*!< pin 5 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD6 BIT(6) /*!< pin 6 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD7 BIT(7) /*!< pin 7 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD8 BIT(8) /*!< pin 8 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD9 BIT(9) /*!< pin 9 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD10 BIT(10) /*!< pin 10 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD11 BIT(11) /*!< pin 11 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD12 BIT(12) /*!< pin 12 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD13 BIT(13) /*!< pin 13 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD14 BIT(14) /*!< pin 14 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD15 BIT(15) /*!< pin 15 set very high output speed when MDx is 0b11 */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0,3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4,6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#ifdef GD32F30X_CL +/* memory map and bit definitions for GD32F30X_CL devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN0_REMAP BITS(13,14) /*!< CAN0 remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ENET_REMAP BIT(21) /*!< ethernet MAC I/O remapping */ +#define AFIO_PCF0_CAN1_REMAP BIT(22) /*!< CAN1 remapping */ +#define AFIO_PCF0_ENET_PHY_SEL BIT(23) /*!< ethernet MII or RMII PHY selection */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1ITR0_REMAP BIT(29) /*!< TIMER1 internal trigger 0 remapping */ +#define AFIO_PCF0_PTP_PPS_REMAP BIT(30) /*!< ethernet PTP PPS remapping */ + +#else +/* memory map and bit definitions for GD32F30X_HD devices and GD32F30X_XD devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN_REMAP BITS(13,14) /*!< CAN remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ADC0_ETRGINS_REMAP BIT(17) /*!< ADC 0 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC0_ETRGREG_REMAP BIT(18) /*!< ADC 0 external trigger regular conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGINS_REMAP BIT(19) /*!< ADC 1 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGREG_REMAP BIT(20) /*!< ADC 1 external trigger regular conversion remapping */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#endif /* GD32F30X_CL */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0,3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4,7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8,11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12,15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0,3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4,7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8,11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12,15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0,3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4,7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8,11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12,15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0,3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4,7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8,11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12,15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_TIMER8_REMAP BIT(5) /*!< TIMER8 remapping */ +#define AFIO_PCF1_TIMER9_REMAP BIT(6) /*!< TIMER9 remapping */ +#define AFIO_PCF1_TIMER10_REMAP BIT(7) /*!< TIMER10 remapping */ +#define AFIO_PCF1_TIMER12_REMAP BIT(8) /*!< TIMER12 remapping */ +#define AFIO_PCF1_TIMER13_REMAP BIT(9) /*!< TIMER13 remapping */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ +#define AFIO_PCF1_CTC_REMAP BITS(11,12) /*!< CTC remapping */ + +/* AFIO_CPSCTL */ +#define AFIO_CPSCTL_CPS_EN BIT(0) /*!< I/O compensation cell enable */ +#define AFIO_CPSCTL_CPS_RDY BIT(8) /*!< I/O compensation cell is ready or not */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ +#define GPIO_OSPEED_MAX ((uint8_t)0x04U) /*!< GPIO very high output speed, max speed more than 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ +#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05U) /*!< output port source F */ +#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06U) /*!< output port source G */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ + +/* AFIO remap mask */ +#define PCF0_USART2_REMAP(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< USART2 remapping */ +#define PCF0_TIMER0_REMAP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< TIMER0 remapping */ +#define PCF0_TIMER1_REMAP(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) /*!< TIMER1 remapping */ +#define PCF0_TIMER2_REMAP(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) /*!< TIMER2 remapping */ +#define PCF0_CAN_REMAP(regval) (BITS(13,14) & ((uint32_t)(regval) << 13)) /*!< CAN remapping */ +#define PCF0_SWJ_CFG(regval) (BITS(24,26) & ((uint32_t)(regval) << 24)) /*!< serial wire JTAG configuration */ +#define PCF1_CTC_REMAP(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) /*!< CTC remapping */ + +/* GPIO remap definitions */ +#define GPIO_SPI0_REMAP AFIO_PCF0_SPI0_REMAP /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP AFIO_PCF0_I2C0_REMAP /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP AFIO_PCF0_USART0_REMAP /*!< USART0 remapping */ +#define GPIO_USART1_REMAP AFIO_PCF0_USART1_REMAP /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140000U | PCF0_USART2_REMAP(1)) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140000U | PCF0_USART2_REMAP(3)) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160000U | PCF0_TIMER0_REMAP(1)) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x00160000U | PCF0_TIMER0_REMAP(3)) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(1)) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(2)) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(3)) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0000U | PCF0_TIMER2_REMAP(2)) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0000U | PCF0_TIMER2_REMAP(3)) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP AFIO_PCF0_TIMER3_REMAP /*!< TIMER3 remapping */ +#define GPIO_PD01_REMAP AFIO_PCF0_PD01_REMAP /*!< PD01 remapping */ +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200000U | (AFIO_PCF0_TIMER4CH3_IREMAP >> 16)) /*!< TIMER4 channel3 internal remapping */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define GPIO_CAN_PARTIAL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(2)) /*!< CAN partial remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_CAN_FULL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(3)) /*!< CAN full remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#endif /* GD32F30X_HD||GD32F30X_XD */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define GPIO_ADC0_ETRGINS_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC0_ETRGINS_REMAP >> 16)) /*!< ADC0 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_ADC0_ETRGREG_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC0_ETRGREG_REMAP >> 16)) /*!< ADC0 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_ADC1_ETRGINS_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC1_ETRGINS_REMAP >> 16)) /*!< ADC1 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_ADC1_ETRGREG_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC1_ETRGREG_REMAP >> 16)) /*!< ADC1 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#endif /* GD32F30X_HD||GD32F30X_XD */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(1) >> 16)) /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */ +#define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(2) >> 16)) /*!< JTAG-DP disabled and SW-DP enabled */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(4) >> 16)) /*!< JTAG-DP disabled and SW-DP disabled */ +#define GPIO_SPI2_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_SPI2_REMAP >> 16)) /*!< SPI2 remapping*/ +#ifdef GD32F30X_CL +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(2)) /*!< CAN0 partial remapping(only for GD32F30X_CL devices) */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(3)) /*!< CAN0 full remapping(only for GD32F30X_CL devices) */ +#define GPIO_ENET_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ENET_REMAP >> 16)) /*!< ENET remapping(only for GD32F30X_CL devices) */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_CAN1_REMAP >> 16)) /*!< CAN1 remapping(only for GD32F30X_CL devices) */ +#define GPIO_TIMER1ITR0_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_TIMER1ITR0_REMAP >> 16)) /*!< TIMER1 internal trigger 0 remapping(only for GD32F30X_CL devices) */ +#define GPIO_PTP_PPS_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_PTP_PPS_REMAP >> 16)) /*!< ethernet PTP PPS remapping(only for GD32F30X_CL devices) */ +#endif /* GD32F30X_CL */ +#define GPIO_TIMER8_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER8_REMAP) /*!< TIMER8 remapping */ +#define GPIO_TIMER9_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER9_REMAP) /*!< TIMER9 remapping */ +#define GPIO_TIMER10_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER10_REMAP) /*!< TIMER10 remapping */ +#define GPIO_TIMER12_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER12_REMAP) /*!< TIMER12 remapping */ +#define GPIO_TIMER13_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER13_REMAP) /*!< TIMER13 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_EXMC_NADV) /*!< EXMC_NADV connect/disconnect */ +#define GPIO_CTC_REMAP0 ((uint32_t)0x801B0000U | PCF1_CTC_REMAP(1)) /*!< CTC remapping(PD15) */ +#define GPIO_CTC_REMAP1 ((uint32_t)0x801B0000U | PCF1_CTC_REMAP(2)) /*!< CTC remapping(PF0) */ + +#ifdef GD32F30X_CL +/* ethernet MII or RMII PHY selection */ +#define GPIO_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< configure ethernet MAC for connection with an MII PHY */ +#define GPIO_ENET_PHY_RMII AFIO_PCF0_ENET_PHY_SEL /*!< configure ethernet MAC for connection with an RMII PHY */ +#endif /* GD32F30X_CL */ + +/* I/O compensation cell enable/disable */ +#define GPIO_COMPENSATION_ENABLE AFIO_CPSCTL_CPS_EN /*!< I/O compensation cell is enable */ +#define GPIO_COMPENSATION_DISABLE ((uint32_t)0x00000000U) /*!< I/O compensation cell is disable */ + +/* function declarations */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin); + +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue); + +#ifdef GD32F30X_CL +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t enet_sel); +#endif /* GD32F30X_CL */ + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); + +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); +/* configure the I/O compensation cell */ +void gpio_compensation_config(uint32_t compensation); +/* check the I/O compensation cell is ready or not */ +FlagStatus gpio_compensation_flag_get(void); + +#endif /* GD32F30X_GPIO_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h new file mode 100644 index 0000000000..169429f60e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h @@ -0,0 +1,355 @@ +/*! + \file gd32f30x_i2c.h + \brief definitions for the I2C + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-04-16, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_I2C_H +#define GD32F30X_I2C_H + +#include "gd32f30x.h" + +/* I2Cx(x=0,1) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ +#define I2C_FMPCFG(i2cx) REG32((i2cx) + 0x90U) /*!< I2C fast-mode-plus configure register */ + +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0,6) /*!< I2CCLK[6:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt inable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_PECV BITS(8,15) /*!< packet error checking value */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode or fast mode plus(master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< duty cycle of fast mode or fast mode plus */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0,6) /*!< maximum rise time in fast/standard mode or fast mode plus(master mode) */ + +/* I2Cx_FMPCFG */ +#define I2C_FMPCFG_FMPEN BIT(0) /*!< fast mode plus enable bit */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +}i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< SCL stretching is enabled */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< SCL stretching is disabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP enable */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP disable */ + +/* fast mode plus enable */ +#define I2C_FAST_MODE_PLUS_ENABLE I2C_FMPCFG_FMPEN /*!< fast mode plus enable */ +#define I2C_FAST_MODE_PLUS_DISABLE ((uint32_t)0x00000000U) /*!< fast mode plus disable */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode or fast mode plus */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< in I2C fast mode or fast mode plus Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< in I2C fast mode or fast mode plus Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); + +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32F30X_I2C_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h new file mode 100644 index 0000000000..392c690bf4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h @@ -0,0 +1,94 @@ +/*! + \file gd32f30x_misc.h + \brief definitions for the MISC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_MISC_H +#define GD32F30X_MISC_H + +#include "gd32f30x.h" + +/* constants definitions */ +/* set the RAM and FLASH base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ + +/* set the NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) + +/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) + +/* priority group - define the pre-emption priority and the subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ + +/* choose the method to enter or exit the lowpower mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ + +#define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT +#define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP +#define SCB_LPM_WAKE_BY_ALL_INT SCB_SCR_SEVONPEND + +/* choose the systick clock source */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */ +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ + +/* function declarations */ +/* set the priority group */ +void nvic_priority_group_set(uint32_t nvic_prigroup); + +/* enable NVIC request */ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); +/* disable NVIC request */ +void nvic_irq_disable(uint8_t nvic_irq); + +/* set the NVIC vector table base address */ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); + +/* set the state of the low power mode */ +void system_lowpower_set(uint8_t lowpower_mode); +/* reset the state of the low power mode */ +void system_lowpower_reset(uint8_t lowpower_mode); + +/* set the systick clock source */ +void systick_clksource_set(uint32_t systick_clksource); + +#endif /* GD32F30X_MISC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h new file mode 100644 index 0000000000..bb7ffdaeb0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h @@ -0,0 +1,187 @@ +/*! + \file gd32f30x_pmu.h + \brief definitions for the PMU + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_PMU_H +#define GD32F30X_PMU_H + +#include "gd32f30x.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5,7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ +#define PMU_CTL_LDLP BIT(10) /*!< low-driver mode when use low power LDO */ +#define PMU_CTL_LDNP BIT(11) /*!< low-driver mode when use normal power LDO */ +#define PMU_CTL_LDOVS BITS(14,15) /*!< LDO output voltage select */ +#define PMU_CTL_HDEN BIT(16) /*!< high-driver mode enable */ +#define PMU_CTL_HDS BIT(17) /*!< high-driver mode switch */ +#define PMU_CTL_LDEN BITS(18,19) /*!< low-driver mode enable in deep-sleep mode */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ +#define PMU_CS_LDOVSRF BIT(14) /*!< LDO voltage select ready flag */ +#define PMU_CS_HDRF BIT(16) /*!< high-driver ready flag */ +#define PMU_CS_HDSRF BIT(17) /*!< high-driver switch ready flag */ +#define PMU_CS_LDRF BITS(18,19) /*!< Low-driver mode ready flag */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval)<<5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.1V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.9V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 3.0V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 3.1V */ + +/* PMU LDO output voltage select definitions */ +#define CTL_LDOVS(regval) (BITS(14,15)&((uint32_t)(regval)<<14)) +#define PMU_LDOVS_LOW CTL_LDOVS(1) /*!< LDO output voltage low mode */ +#define PMU_LDOVS_MID CTL_LDOVS(2) /*!< LDO output voltage mid mode */ +#define PMU_LDOVS_HIGH CTL_LDOVS(3) /*!< LDO output voltage high mode */ + +/* PMU high-driver mode switch */ +#define CTL_HDS(regval) (BIT(17)&((uint32_t)(regval)<<17)) +#define PMU_HIGHDR_SWITCH_NONE CTL_HDS(0) /*!< no high-driver mode switch */ +#define PMU_HIGHDR_SWITCH_EN CTL_HDS(1) /*!< high-driver mode switch */ + +/* PMU low-driver mode when use low power LDO */ +#define CTL_LDLP(regval) (BIT(10)&((uint32_t)(regval)<<10)) +#define PMU_NORMALDR_LOWPWR CTL_LDLP(0) /*!< normal driver when use low power LDO */ +#define PMU_LOWDR_LOWPWR CTL_LDLP(1) /*!< low-driver mode enabled when LDEN is 11 and use low power LDO */ + +/* PMU low-driver mode when use normal power LDO */ +#define CTL_LDNP(regval) (BIT(11)&((uint32_t)(regval)<<11)) +#define PMU_NORMALDR_NORMALPWR CTL_LDNP(0) /*!< normal driver when use normal power LDO */ +#define PMU_LOWDR_NORMALPWR CTL_LDNP(1) /*!< low-driver mode enabled when LDEN is 11 and use normal power LDO */ + +/* PMU low power mode ready flag definitions */ +#define CS_LDRF(regval) (BITS(18,19)&((uint32_t)(regval)<<18)) +#define PMU_LDRF_NORMAL CS_LDRF(0) /*!< normal driver in deep-sleep mode */ +#define PMU_LDRF_LOWDRIVER CS_LDRF(3) /*!< low-driver mode in deep-sleep mode */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ +#define PMU_FLAG_LDOVSRF PMU_CS_LDOVSRF /*!< LDO voltage select ready flag */ +#define PMU_FLAG_HDRF PMU_CS_HDRF /*!< high-driver ready flag */ +#define PMU_FLAG_HDSRF PMU_CS_HDSRF /*!< high-driver switch ready flag */ +#define PMU_FLAG_LDRF PMU_CS_LDRF /*!< low-driver mode ready flag */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* select LDO output voltage */ +void pmu_ldo_output_select(uint32_t ldo_output); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* functions of low-driver mode and high-driver mode in deep-sleep mode */ +/* switch high-driver mode */ +void pmu_highdriver_switch_select(uint32_t highdr_switch); +/* enable high-driver mode */ +void pmu_highdriver_mode_enable(void); +/* disable high-driver mode */ +void pmu_highdriver_mode_disable(void); +/* enable low-driver mode in deep-sleep mode */ +void pmu_lowdriver_mode_enable(void); +/* disable low-driver mode in deep-sleep mode */ +void pmu_lowdriver_mode_disable(void); +/* in deep-sleep mode, driver mode when use low power LDO */ +void pmu_lowpower_driver_config(uint32_t mode); +/* in deep-sleep mode, driver mode when use normal power LDO */ +void pmu_normalpower_driver_config(uint32_t mode); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable backup domain write */ +void pmu_backup_write_enable(void); +/* disable backup domain write */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); + +#endif /* GD32F30X_PMU_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h new file mode 100644 index 0000000000..d3724e7811 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h @@ -0,0 +1,1053 @@ +/*! + \file gd32f30x_rcu.h + \brief definitions for the RCU + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_RCU_H +#define GD32F30X_RCU_H + +#include "gd32f30x.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ +#define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ +#define RCU_ADDAPB1RST REG32(RCU + 0xE0U) /*!< APB1 additional reset register */ +#define RCU_ADDAPB1EN REG32(RCU + 0xE4U) /*!< APB1 additional enable register */ +#elif defined(GD32F30X_CL) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHBRST REG32(RCU + 0x28U) /*!< AHB reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ +#define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ +#define RCU_ADDAPB1RST REG32(RCU + 0xE0U) /*!< APB1 additional reset register */ +#define RCU_ADDAPB1EN REG32(RCU + 0xE4U) /*!< APB1 additional enable register */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* bits definitions */ +/* RCU_CTL */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#elif defined(GD32F30X_CL) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_CFG0 */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0 BIT(17) /*!< PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBDPSC BITS(22,23) /*!< USBD clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,26) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_PLLMF_4 BIT(27) /*!< bit 4 of PLLMF */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_5 BIT(30) /*!< bit 5 of PLLMF */ +#define RCU_CFG0_USBDPSC_2 BIT(31) /*!< bit 2 of USBDPSC */ +#elif defined(GD32F30X_CL) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ +#define RCU_CFG0_PLLMF_5 BIT(30) /*!< bit 5 of PLLMF */ +#define RCU_CFG0_USBFSPSC_2 BIT(31) /*!< bit 2 of USBFSPSC */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_INT */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K Stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL Stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M Stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL Stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#elif defined(GD32F30X_CL) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ +#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ +#ifndef GD32F30X_CL +#define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD +#define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ +#endif /* GD32F30X_HD */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ +#ifndef GD32F30X_HD +#define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ +#endif /* GD32F30X_HD */ +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_APB1RST_USBDRST BIT(23) /*!< USBD reset */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#ifdef GD32F30X_CL +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#endif /* GD32F30X_CL */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHBEN */ +#define RCU_AHBEN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHBEN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHBEN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHBEN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHBEN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHBEN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_AHBEN_SDIOEN BIT(10) /*!< SDIO clock enable */ +#elif defined(GD32F30X_CL) +#define RCU_AHBEN_USBFSEN BIT(12) /*!< USBFS clock enable */ +#define RCU_AHBEN_ENETEN BIT(14) /*!< ENET clock enable */ +#define RCU_AHBEN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ +#define RCU_AHBEN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ +#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ +#ifndef GD32F30X_CL +#define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD +#define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ +#endif /* GD32F30X_HD */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#ifndef GD32F30X_HD +#define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ +#endif /* GD32F30X_HD */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_APB1EN_USBDEN BIT(23) /*!< USBD clock enable */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#ifdef GD32F30X_CL +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#endif /* GD32F30X_CL */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_LXTALDRI BITS(3,4) /*!< LXTAL drive capability */ +#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +#ifdef GD32F30X_CL +/* RCU_AHBRST */ +#define RCU_AHBRST_USBFSRST BIT(12) /*!< USBFS reset */ +#define RCU_AHBRST_ENETRST BIT(14) /*!< ENET reset */ +#endif /* GD32F30X_CL */ + +/* RCU_CFG1 */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CFG1_ADCPSC_3 BIT(29) /*!< bit 4 of ADCPSC */ +#define RCU_CFG1_PLLPRESEL BIT(30) /*!< PLL clock source selection */ +#elif defined(GD32F30X_CL) +#define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ +#define RCU_CFG1_ADCPSC_3 BIT(29) /*!< bit 4 of ADCPSC */ +#define RCU_CFG1_PLLPRESEL BIT(30) /*!< PLL clock source selection */ +#define RCU_CFG1_PLL2MF_4 BIT(31) /*!< bit 5 of PLL2MF */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ + +/* RCU_ADDCTL */ +#define RCU_ADDCTL_CK48MSEL BIT(0) /*!< 48MHz clock selection */ +#define RCU_ADDCTL_IRC48MEN BIT(16) /*!< internal 48MHz RC oscillator enable */ +#define RCU_ADDCTL_IRC48MSTB BIT(17) /*!< internal 48MHz RC oscillator clock stabilization flag */ +#define RCU_ADDCTL_IRC48MCAL BITS(24,31) /*!< internal 48MHz RC oscillator calibration value register */ + +/* RCU_ADDINT */ +#define RCU_ADDINT_IRC48MSTBIF BIT(6) /*!< IRC48M stabilization interrupt flag */ +#define RCU_ADDINT_IRC48MSTBIE BIT(14) /*!< internal 48 MHz RC oscillator stabilization interrupt enable */ +#define RCU_ADDINT_IRC48MSTBIC BIT(22) /*!< internal 48 MHz RC oscillator stabilization interrupt clear */ + +/* RCU_ADDAPB1RST */ +#define RCU_ADDAPB1RST_CTCRST BIT(27) /*!< CTC reset */ + +/* RCU_ADDAPB1EN */ +#define RCU_ADDAPB1EN_CTCEN BIT(27) /*!< CTC clock enable */ + + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHBEN_REG_OFFSET 0x14U /*!< AHB enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ +#define ADD_APB1EN_REG_OFFSET 0xE4U /*!< APB1 additional enable register offset */ + +/* peripherals reset */ +#define AHBRST_REG_OFFSET 0x28U /*!< AHB reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define ADD_APB1RST_REG_OFFSET 0xE0U /*!< APB1 additional reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source/clock register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ +#define ADDCTL_REG_OFFSET 0xC0U /*!< additional clock control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< clock interrupt register offset */ +#define ADDINT_REG_OFFSET 0xCCU /*!< additional clock interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< clock configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< clock configuration register 1 offset */ + +/* peripheral clock enable */ +typedef enum +{ + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U), /*!< EXMC clock */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_SDIO = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 10U), /*!< SDIO clock */ +#elif defined(GD32F30X_CL) + RCU_USBFS = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U), /*!< USBFS clock */ + RCU_ENET = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 14U), /*!< ENET clock */ + RCU_ENETTX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 15U), /*!< ENETTX clock */ + RCU_ENETRX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 16U), /*!< ENETRX clock */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ +#ifndef GD32F30X_HD + RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ + RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ +#endif /* GD32F30X_HD */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_USBD = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< USBD clock */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ +#ifdef GD32F30X_CL + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ +#endif /* GD32F30X_CL */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + RCU_CTC = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 27U), /*!< CTC clock */ + + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ + RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ +#ifndef GD32F30X_CL + RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD + RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ + RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ + RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ +#endif /* GD32F30X_HD */ +}rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum +{ + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U), /*!< FMC clock */ +}rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum +{ + /* AHB peripherals */ +#ifdef GD32F30X_CL + RCU_USBFSRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 14U), /*!< ENET clock reset */ +#endif /* GD32F30X_CL */ + + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ +#ifndef GD32F30X_HD + RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ + RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ +#endif /* GD32F30X_HD */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_USBDRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< USBD clock reset */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ +#ifdef GD32F30X_CL + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ +#endif /* GD32F30X_CL */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + RCU_CTCRST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 27U), /*!< RTC clock reset */ + + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ + RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ +#ifndef GD32F30X_CL + RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD + RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ + RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ + RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ +#endif /* GD32F30X_HD */ +}rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum +{ + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ +#ifdef GD32F30X_CL + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ +#endif /* GD32F30X_CL */ + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + RCU_FLAG_IRC48MSTB = RCU_REGIDX_BIT(ADDCTL_REG_OFFSET, 17U), /*!< IRC48M stabilization flags */ + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +}rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ +#ifdef GD32F30X_CL + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ +#endif /* GD32F30X_CL */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ + RCU_INT_FLAG_IRC48MSTB = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 6U), /*!< IRC48M stabilization interrupt flag */ +}rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ +#ifdef GD32F30X_CL + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ +#endif /* GD32F30X_CL */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ + RCU_INT_FLAG_IRC48MSTB_CLR = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 22U), /*!< internal 48 MHz RC oscillator stabilization interrupt clear */ +}rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum +{ + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ +#ifdef GD32F30X_CL + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ +#endif /* GD32F30X_CL */ + RCU_INT_IRC48MSTB = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 14U), /*!< internal 48 MHz RC oscillator stabilization interrupt */ +}rcu_int_enum; + +/* oscillator types */ +typedef enum +{ + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_IRC48M = RCU_REGIDX_BIT(ADDCTL_REG_OFFSET, 16U), /*!< IRC48M */ + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ +#ifdef GD32F30X_CL + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ +#endif /* GD32F30X_CL */ +}rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum +{ + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +}rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source select */ +#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler select */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ +#define RCU_CKADC_CKAHB_DIV5 ((uint32_t)0x00000008U) /*!< ADC prescaler select CK_AHB/5 */ +#define RCU_CKADC_CKAHB_DIV6 ((uint32_t)0x00000009U) /*!< ADC prescaler select CK_AHB/6 */ +#define RCU_CKADC_CKAHB_DIV10 ((uint32_t)0x0000000AU) /*!< ADC prescaler select CK_AHB/10 */ +#define RCU_CKADC_CKAHB_DIV20 ((uint32_t)0x0000000BU) /*!< ADC prescaler select CK_AHB/20 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL_IRC48M RCU_CFG0_PLLSEL /*!< HXTAL or IRC48M selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ +#define PLLMF_5 RCU_CFG0_PLLMF_5 /* bit 5 of PLLMF */ +#define PLLMF_4_5 (PLLMF_4 | PLLMF_5) /* bit 4 and 5 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#if(defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_PLL_MUL15 CFG0_PLLMF(13) /*!< PLL source clock multiply by 15 */ +#elif defined(GD32F30X_CL) +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ +#define RCU_PLL_MUL33 (PLLMF_5 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 33 */ +#define RCU_PLL_MUL34 (PLLMF_5 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 34 */ +#define RCU_PLL_MUL35 (PLLMF_5 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 35 */ +#define RCU_PLL_MUL36 (PLLMF_5 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 36 */ +#define RCU_PLL_MUL37 (PLLMF_5 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 37 */ +#define RCU_PLL_MUL38 (PLLMF_5 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 38 */ +#define RCU_PLL_MUL39 (PLLMF_5 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 39 */ +#define RCU_PLL_MUL40 (PLLMF_5 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 40 */ +#define RCU_PLL_MUL41 (PLLMF_5 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 41 */ +#define RCU_PLL_MUL42 (PLLMF_5 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 42 */ +#define RCU_PLL_MUL43 (PLLMF_5 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 43 */ +#define RCU_PLL_MUL44 (PLLMF_5 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 44 */ +#define RCU_PLL_MUL45 (PLLMF_5 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 45 */ +#define RCU_PLL_MUL46 (PLLMF_5 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 46 */ +#define RCU_PLL_MUL47 (PLLMF_5 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 47 */ +#define RCU_PLL_MUL48 (PLLMF_5 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 48 */ +#define RCU_PLL_MUL49 (PLLMF_4_5 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 49 */ +#define RCU_PLL_MUL50 (PLLMF_4_5 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 50 */ +#define RCU_PLL_MUL51 (PLLMF_4_5 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 51 */ +#define RCU_PLL_MUL52 (PLLMF_4_5 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 52 */ +#define RCU_PLL_MUL53 (PLLMF_4_5 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 53 */ +#define RCU_PLL_MUL54 (PLLMF_4_5 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 54 */ +#define RCU_PLL_MUL55 (PLLMF_4_5 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 55 */ +#define RCU_PLL_MUL56 (PLLMF_4_5 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 56 */ +#define RCU_PLL_MUL57 (PLLMF_4_5 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 57 */ +#define RCU_PLL_MUL58 (PLLMF_4_5 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 58 */ +#define RCU_PLL_MUL59 (PLLMF_4_5 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 59 */ +#define RCU_PLL_MUL60 (PLLMF_4_5 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 60 */ +#define RCU_PLL_MUL61 (PLLMF_4_5 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 61 */ +#define RCU_PLL_MUL62 (PLLMF_4_5 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 62 */ +#define RCU_PLL_MUL63 (PLLMF_4_5 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 63 */ + +#if(defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define USBPSC_2 RCU_CFG0_USBDPSC_2 +#elif defined(GD32F30X_CL) +#define USBPSC_2 RCU_CFG0_USBFSPSC_2 +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* USBD/USBFS prescaler select */ +#define CFG0_USBPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBPSC(0) /*!< USBD/USBFS prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBPSC(1) /*!< USBD/USBFS prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBPSC(2) /*!< USBD/USBFS prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBPSC(3) /*!< USBD/USBFS prescaler select CK_PLL/2 */ +#define RCU_CKUSB_CKPLL_DIV3 (USBPSC_2 |CFG0_USBPSC(0)) /*!< USBD/USBFS prescaler select CK_PLL/3 */ +#define RCU_CKUSB_CKPLL_DIV3_5 (USBPSC_2 |CFG0_USBPSC(1)) /*!< USBD/USBFS prescaler select CK_PLL/3.5 */ +#define RCU_CKUSB_CKPLL_DIV4 (USBPSC_2 |CFG0_USBPSC(2)) /*!< USBD/USBFS prescaler select CK_PLL/4 */ + +/* CKOUT0 Clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#ifdef GD32F30X_CL +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ +#endif /* GD32F30X_CL */ + +/* LXTAL drive capability */ +#define BDCTL_LXTALDRI(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) +#define RCU_LXTAL_LOWDRI BDCTL_LXTALDRI(0) /*!< lower driving capability */ +#define RCU_LXTAL_MED_LOWDRI BDCTL_LXTALDRI(1) /*!< medium low driving capability */ +#define RCU_LXTAL_MED_HIGHDRI BDCTL_LXTALDRI(2) /*!< medium high driving capability */ +#define RCU_LXTAL_HIGHDRI BDCTL_LXTALDRI(3) /*!< higher driving capability */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV_128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock not divided */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock not divided */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define PLL2MF_4 RCU_CFG1_PLL2MF_4 /* bit 4 of PLL2MF */ + +#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ +#define RCU_PLL2_MUL18 (PLL2MF_4 | CFG1_PLL2MF(0)) /*!< PLL2 source clock multiply by 18 */ +#define RCU_PLL2_MUL19 (PLL2MF_4 | CFG1_PLL2MF(1)) /*!< PLL2 source clock multiply by 19 */ +#define RCU_PLL2_MUL21 (PLL2MF_4 | CFG1_PLL2MF(3)) /*!< PLL2 source clock multiply by 21 */ +#define RCU_PLL2_MUL22 (PLL2MF_4 | CFG1_PLL2MF(4)) /*!< PLL2 source clock multiply by 22 */ +#define RCU_PLL2_MUL23 (PLL2MF_4 | CFG1_PLL2MF(5)) /*!< PLL2 source clock multiply by 23 */ +#define RCU_PLL2_MUL24 (PLL2MF_4 | CFG1_PLL2MF(6)) /*!< PLL2 source clock multiply by 24 */ +#define RCU_PLL2_MUL25 (PLL2MF_4 | CFG1_PLL2MF(7)) /*!< PLL2 source clock multiply by 25 */ +#define RCU_PLL2_MUL26 (PLL2MF_4 | CFG1_PLL2MF(8)) /*!< PLL2 source clock multiply by 26 */ +#define RCU_PLL2_MUL27 (PLL2MF_4 | CFG1_PLL2MF(9)) /*!< PLL2 source clock multiply by 27 */ +#define RCU_PLL2_MUL28 (PLL2MF_4 | CFG1_PLL2MF(10)) /*!< PLL2 source clock multiply by 28 */ +#define RCU_PLL2_MUL29 (PLL2MF_4 | CFG1_PLL2MF(11)) /*!< PLL2 source clock multiply by 29 */ +#define RCU_PLL2_MUL30 (PLL2MF_4 | CFG1_PLL2MF(12)) /*!< PLL2 source clock multiply by 30 */ +#define RCU_PLL2_MUL31 (PLL2MF_4 | CFG1_PLL2MF(13)) /*!< PLL2 source clock multiply by 31 */ +#define RCU_PLL2_MUL32 (PLL2MF_4 | CFG1_PLL2MF(14)) /*!< PLL2 source clock multiply by 32 */ +#define RCU_PLL2_MUL40 (PLL2MF_4 | CFG1_PLL2MF(15)) /*!< PLL2 source clock multiply by 40 */ + +#ifdef GD32F30X_CL +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL_IRC48M ((uint32_t)0x00000000U) /*!< HXTAL or IRC48M selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ +#endif /* GD32F30X_CL */ + +/* PLL input clock source selection */ +#define RCU_PLLPRESRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PLL source clock */ +#define RCU_PLLPRESRC_IRC48M RCU_CFG1_PLLPRESEL /*!< CK_PLL selected as PREDV0 input source clock */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(0) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(1) /*!< core voltage is 0.9V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_8 DSV_DSLPVS(2) /*!< core voltage is 0.8V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_7 DSV_DSLPVS(3) /*!< core voltage is 0.7V in deep-sleep mode */ + +/* 48MHz clock selection */ +#define RCU_CK48MSRC_CKPLL ((uint32_t)0x00000000U) /*!< use CK_PLL clock */ +#define RCU_CK48MSRC_IRC48M RCU_ADDCTL_CK48MSEL /*!< select IRC48M clock */ + +/* function declarations */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src); +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); +/* configure the PLL clock source preselection */ +void rcu_pllpresel_config(uint32_t pll_presel); +#if(defined(GD32F30X_HD) || defined(GD32F30X_XD)) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_div); +#elif defined(GD32F30X_CL) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBD/USBFS prescaler factor */ +void rcu_usb_clock_config(uint32_t usb_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); +#ifdef GD32F30X_CL +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); +#endif /* GD32F30X_CL */ +/* configure the CK48M clock selection */ +void rcu_ck48m_clock_config(uint32_t ck48m_clock_source); + + +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum interrupt); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum interrupt); + +/* configure the LXTAL drive capability */ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval); + +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32F30X_RCU_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h new file mode 100644 index 0000000000..3aace0d0c3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h @@ -0,0 +1,138 @@ +/*! + \file gd32f30x_rtc.h + \brief definitions for the RTC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_RTC_H +#define GD32F30X_RTC_H + +#include "gd32f30x.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSC */ +#define RTC_PSCH_PSC BITS(0, 3) /*!< prescaler high value */ +#define RTC_PSCL_PSC BITS(0, 15) /*!< prescaler low value */ + +/* RTC_DIV */ +#define RTC_DIVH_DIV BITS(0, 3) /*!< divider high value */ +#define RTC_DIVL_DIV BITS(0, 15) /*!< divider low value */ + +/* RTC_CNT */ +#define RTC_CNTH_CNT BITS(0, 15) /*!< counter high value */ +#define RTC_CNTL_CNT BITS(0, 15) /*!< counter low value */ + +/* RTC_ALRM */ +#define RTC_ALRMH_ALRM BITS(0, 15) /*!< alarm high value */ +#define RTC_ALRML_ALRM BITS(0, 15) /*!< alarm low value */ + +/* constants definitions */ +#define RTC_HIGH_VALUE 0x000F0000U /*!< RTC high value */ +#define RTC_LOW_VALUE 0x0000FFFFU /*!< RTC low value */ + +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); + +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); + +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); + +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); + +#endif /* GD32F30X_RTC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h new file mode 100644 index 0000000000..6555fc1039 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h @@ -0,0 +1,434 @@ +/*! + \file gd32f30x_sdio.h + \brief definitions for the SDIO + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_SDIO_H +#define GD32F30X_SDIO_H + +#include "gd32f30x.h" + +/* SDIO definitions */ +#define SDIO SDIO_BASE + +/* registers definitions */ +#define SDIO_PWRCTL REG32(SDIO + 0x00U) /*!< SDIO power control register */ +#define SDIO_CLKCTL REG32(SDIO + 0x04U) /*!< SDIO clock control register */ +#define SDIO_CMDAGMT REG32(SDIO + 0x08U) /*!< SDIO command argument register */ +#define SDIO_CMDCTL REG32(SDIO + 0x0CU) /*!< SDIO command control register */ +#define SDIO_RSPCMDIDX REG32(SDIO + 0x10U) /*!< SDIO command index response register */ +#define SDIO_RESP0 REG32(SDIO + 0x14U) /*!< SDIO response register 0 */ +#define SDIO_RESP1 REG32(SDIO + 0x18U) /*!< SDIO response register 1 */ +#define SDIO_RESP2 REG32(SDIO + 0x1CU) /*!< SDIO response register 2 */ +#define SDIO_RESP3 REG32(SDIO + 0x20U) /*!< SDIO response register 3 */ +#define SDIO_DATATO REG32(SDIO + 0x24U) /*!< SDIO data timeout register */ +#define SDIO_DATALEN REG32(SDIO + 0x28U) /*!< SDIO data length register */ +#define SDIO_DATACTL REG32(SDIO + 0x2CU) /*!< SDIO data control register */ +#define SDIO_DATACNT REG32(SDIO + 0x30U) /*!< SDIO data counter register */ +#define SDIO_STAT REG32(SDIO + 0x34U) /*!< SDIO status register */ +#define SDIO_INTC REG32(SDIO + 0x38U) /*!< SDIO interrupt clear register */ +#define SDIO_INTEN REG32(SDIO + 0x3CU) /*!< SDIO interrupt enable register */ +#define SDIO_FIFOCNT REG32(SDIO + 0x48U) /*!< SDIO FIFO counter register */ +#define SDIO_FIFO REG32(SDIO + 0x80U) /*!< SDIO FIFO data register */ + +/* bits definitions */ +/* SDIO_PWRCTL */ +#define SDIO_PWRCTL_PWRCTL BITS(0,1) /*!< SDIO power control bits */ + +/* SDIO_CLKCTL */ +#define SDIO_CLKCTL_DIV BITS(0,7) /*!< clock division */ +#define SDIO_CLKCTL_CLKEN BIT(8) /*!< SDIO_CLK clock output enable bit */ +#define SDIO_CLKCTL_CLKPWRSAV BIT(9) /*!< SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLKCTL_CLKBYP BIT(10) /*!< clock bypass enable bit */ +#define SDIO_CLKCTL_BUSMODE BITS(11,12) /*!< SDIO card bus mode control bit */ +#define SDIO_CLKCTL_CLKEDGE BIT(13) /*!< SDIO_CLK clock edge selection bit */ +#define SDIO_CLKCTL_HWCLKEN BIT(14) /*!< hardware clock control enable bit */ +#define SDIO_CLKCTL_DIV8 BIT(31) /*!< MSB of clock division */ + +/* SDIO_CMDAGMT */ +#define SDIO_CMDAGMT_CMDAGMT BITS(0,31) /*!< SDIO card command argument */ + +/* SDIO_CMDCTL */ +#define SDIO_CMDCTL_CMDIDX BITS(0,5) /*!< command index */ +#define SDIO_CMDCTL_CMDRESP BITS(6,7) /*!< command response type bits */ +#define SDIO_CMDCTL_INTWAIT BIT(8) /*!< interrupt wait instead of timeout */ +#define SDIO_CMDCTL_WAITDEND BIT(9) /*!< wait for ends of data transfer */ +#define SDIO_CMDCTL_CSMEN BIT(10) /*!< command state machine(CSM) enable bit */ +#define SDIO_CMDCTL_SUSPEND BIT(11) /*!< SD I/O suspend command(SD I/O only) */ +#define SDIO_CMDCTL_ENCMDC BIT(12) /*!< CMD completion signal enabled (CE-ATA only) */ +#define SDIO_CMDCTL_NINTEN BIT(13) /*!< no CE-ATA interrupt (CE-ATA only) */ +#define SDIO_CMDCTL_ATAEN BIT(14) /*!< CE-ATA command enable(CE-ATA only) */ + +/* SDIO_DATATO */ +#define SDIO_DATATO_DATATO BITS(0,31) /*!< data timeout period */ + +/* SDIO_DATALEN */ +#define SDIO_DATALEN_DATALEN BITS(0,24) /*!< data transfer length */ + +/* SDIO_DATACTL */ +#define SDIO_DATACTL_DATAEN BIT(0) /*!< data transfer enabled bit */ +#define SDIO_DATACTL_DATADIR BIT(1) /*!< data transfer direction */ +#define SDIO_DATACTL_TRANSMOD BIT(2) /*!< data transfer mode */ +#define SDIO_DATACTL_DMAEN BIT(3) /*!< DMA enable bit */ +#define SDIO_DATACTL_BLKSZ BITS(4,7) /*!< data block size */ +#define SDIO_DATACTL_RWEN BIT(8) /*!< read wait mode enabled(SD I/O only) */ +#define SDIO_DATACTL_RWSTOP BIT(9) /*!< read wait stop(SD I/O only) */ +#define SDIO_DATACTL_RWTYPE BIT(10) /*!< read wait type(SD I/O only) */ +#define SDIO_DATACTL_IOEN BIT(11) /*!< SD I/O specific function enable(SD I/O only) */ + +/* SDIO_STAT */ +#define SDIO_STAT_CCRCERR BIT(0) /*!< command response received (CRC check failed) */ +#define SDIO_STAT_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) */ +#define SDIO_STAT_CMDTMOUT BIT(2) /*!< command response timeout */ +#define SDIO_STAT_DTTMOUT BIT(3) /*!< data timeout */ +#define SDIO_STAT_TXURE BIT(4) /*!< transmit FIFO underrun error occurs */ +#define SDIO_STAT_RXORE BIT(5) /*!< received FIFO overrun error occurs */ +#define SDIO_STAT_CMDRECV BIT(6) /*!< command response received (CRC check passed) */ +#define SDIO_STAT_CMDSEND BIT(7) /*!< command sent (no response required) */ +#define SDIO_STAT_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) */ +#define SDIO_STAT_STBITE BIT(9) /*!< start bit error in the bus */ +#define SDIO_STAT_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) */ +#define SDIO_STAT_CMDRUN BIT(11) /*!< command transmission in progress */ +#define SDIO_STAT_TXRUN BIT(12) /*!< data transmission in progress */ +#define SDIO_STAT_RXRUN BIT(13) /*!< data reception in progress */ +#define SDIO_STAT_TFH BIT(14) /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */ +#define SDIO_STAT_RFH BIT(15) /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */ +#define SDIO_STAT_TFF BIT(16) /*!< transmit FIFO is full */ +#define SDIO_STAT_RFF BIT(17) /*!< receive FIFO is full */ +#define SDIO_STAT_TFE BIT(18) /*!< transmit FIFO is empty */ +#define SDIO_STAT_RFE BIT(19) /*!< receive FIFO is empty */ +#define SDIO_STAT_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO */ +#define SDIO_STAT_RXDTVAL BIT(21) /*!< data is valid in receive FIFO */ +#define SDIO_STAT_SDIOINT BIT(22) /*!< SD I/O interrupt received */ +#define SDIO_STAT_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) */ + +/* SDIO_INTC */ +#define SDIO_INTC_CCRCERRC BIT(0) /*!< CCRCERR flag clear bit */ +#define SDIO_INTC_DTCRCERRC BIT(1) /*!< DTCRCERR flag clear bit */ +#define SDIO_INTC_CMDTMOUTC BIT(2) /*!< CMDTMOUT flag clear bit */ +#define SDIO_INTC_DTTMOUTC BIT(3) /*!< DTTMOUT flag clear bit */ +#define SDIO_INTC_TXUREC BIT(4) /*!< TXURE flag clear bit */ +#define SDIO_INTC_RXOREC BIT(5) /*!< RXORE flag clear bit */ +#define SDIO_INTC_CMDRECVC BIT(6) /*!< CMDRECV flag clear bit */ +#define SDIO_INTC_CMDSENDC BIT(7) /*!< CMDSEND flag clear bit */ +#define SDIO_INTC_DTENDC BIT(8) /*!< DTEND flag clear bit */ +#define SDIO_INTC_STBITEC BIT(9) /*!< STBITE flag clear bit */ +#define SDIO_INTC_DTBLKENDC BIT(10) /*!< DTBLKEND flag clear bit */ +#define SDIO_INTC_SDIOINTC BIT(22) /*!< SDIOINT flag clear bit */ +#define SDIO_INTC_ATAENDC BIT(23) /*!< ATAEND flag clear bit */ + +/* SDIO_INTEN */ +#define SDIO_INTEN_CCRCERRIE BIT(0) /*!< command response CRC fail interrupt enable */ +#define SDIO_INTEN_DTCRCERRIE BIT(1) /*!< data CRC fail interrupt enable */ +#define SDIO_INTEN_CMDTMOUTIE BIT(2) /*!< command response timeout interrupt enable */ +#define SDIO_INTEN_DTTMOUTIE BIT(3) /*!< data timeout interrupt enable */ +#define SDIO_INTEN_TXUREIE BIT(4) /*!< transmit FIFO underrun error interrupt enable */ +#define SDIO_INTEN_RXOREIE BIT(5) /*!< received FIFO overrun error interrupt enable */ +#define SDIO_INTEN_CMDRECVIE BIT(6) /*!< command response received interrupt enable */ +#define SDIO_INTEN_CMDSENDIE BIT(7) /*!< command sent interrupt enable */ +#define SDIO_INTEN_DTENDIE BIT(8) /*!< data end interrupt enable */ +#define SDIO_INTEN_STBITEIE BIT(9) /*!< start bit error interrupt enable */ +#define SDIO_INTEN_DTBLKENDIE BIT(10) /*!< data block end interrupt enable */ +#define SDIO_INTEN_CMDRUNIE BIT(11) /*!< command transmission interrupt enable */ +#define SDIO_INTEN_TXRUNIE BIT(12) /*!< data transmission interrupt enable */ +#define SDIO_INTEN_RXRUNIE BIT(13) /*!< data reception interrupt enable */ +#define SDIO_INTEN_TFHIE BIT(14) /*!< transmit FIFO half empty interrupt enable */ +#define SDIO_INTEN_RFHIE BIT(15) /*!< receive FIFO half full interrupt enable */ +#define SDIO_INTEN_TFFIE BIT(16) /*!< transmit FIFO full interrupt enable */ +#define SDIO_INTEN_RFFIE BIT(17) /*!< receive FIFO full interrupt enable */ +#define SDIO_INTEN_TFEIE BIT(18) /*!< transmit FIFO empty interrupt enable */ +#define SDIO_INTEN_RFEIE BIT(19) /*!< receive FIFO empty interrupt enable */ +#define SDIO_INTEN_TXDTVALIE BIT(20) /*!< data valid in transmit FIFO interrupt enable */ +#define SDIO_INTEN_RXDTVALIE BIT(21) /*!< data valid in receive FIFO interrupt enable */ +#define SDIO_INTEN_SDIOINTIE BIT(22) /*!< SD I/O interrupt received interrupt enable */ +#define SDIO_INTEN_ATAENDIE BIT(23) /*!< CE-ATA command completion signal received interrupt enable */ + +/* SDIO_FIFO */ +#define SDIO_FIFO_FIFODT BITS(0,31) /*!< receive FIFO data or transmit FIFO data */ + +/* constants definitions */ +/* SDIO flags */ +#define SDIO_FLAG_CCRCERR BIT(0) /*!< command response received (CRC check failed) flag */ +#define SDIO_FLAG_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) flag */ +#define SDIO_FLAG_CMDTMOUT BIT(2) /*!< command response timeout flag */ +#define SDIO_FLAG_DTTMOUT BIT(3) /*!< data timeout flag */ +#define SDIO_FLAG_TXURE BIT(4) /*!< transmit FIFO underrun error occurs flag */ +#define SDIO_FLAG_RXORE BIT(5) /*!< received FIFO overrun error occurs flag */ +#define SDIO_FLAG_CMDRECV BIT(6) /*!< command response received (CRC check passed) flag */ +#define SDIO_FLAG_CMDSEND BIT(7) /*!< command sent (no response required) flag */ +#define SDIO_FLAG_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) flag */ +#define SDIO_FLAG_STBITE BIT(9) /*!< start bit error in the bus flag */ +#define SDIO_FLAG_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) flag */ +#define SDIO_FLAG_CMDRUN BIT(11) /*!< command transmission in progress flag */ +#define SDIO_FLAG_TXRUN BIT(12) /*!< data transmission in progress flag */ +#define SDIO_FLAG_RXRUN BIT(13) /*!< data reception in progress flag */ +#define SDIO_FLAG_TFH BIT(14) /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */ +#define SDIO_FLAG_RFH BIT(15) /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */ +#define SDIO_FLAG_TFF BIT(16) /*!< transmit FIFO is full flag */ +#define SDIO_FLAG_RFF BIT(17) /*!< receive FIFO is full flag */ +#define SDIO_FLAG_TFE BIT(18) /*!< transmit FIFO is empty flag */ +#define SDIO_FLAG_RFE BIT(19) /*!< receive FIFO is empty flag */ +#define SDIO_FLAG_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO flag */ +#define SDIO_FLAG_RXDTVAL BIT(21) /*!< data is valid in receive FIFO flag */ +#define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ +#define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ + +/* SDIO interrupt enable or disable */ +#define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt flag */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt flag */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt flag */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt flag */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt flag */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt flag */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt flag */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt flag */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt flag */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt flag */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt flag */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt flag */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt flag */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt flag */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt flag */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt flag */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt flag */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt flag */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt flag */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt flag */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt flag */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt flag */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt flag */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt flag */ + +/* SDIO power control */ +#define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ +#define SDIO_POWER_ON PWRCTL_PWRCTL(3) /*!< SDIO power on */ + +/* SDIO card bus mode control */ +#define CLKCTL_BUSMODE(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) +#define SDIO_BUSMODE_1BIT CLKCTL_BUSMODE(0) /*!< 1-bit SDIO card bus mode */ +#define SDIO_BUSMODE_4BIT CLKCTL_BUSMODE(1) /*!< 4-bit SDIO card bus mode */ +#define SDIO_BUSMODE_8BIT CLKCTL_BUSMODE(2) /*!< 8-bit SDIO card bus mode */ + +/* SDIO_CLK clock edge selection */ +#define SDIO_SDIOCLKEDGE_RISING (uint32_t)0x00000000U /*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */ +#define SDIO_SDIOCLKEDGE_FALLING SDIO_CLKCTL_CLKEDGE /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */ + +/* clock bypass enable or disable */ +#define SDIO_CLOCKBYPASS_DISABLE (uint32_t)0x00000000U /*!< no bypass */ +#define SDIO_CLOCKBYPASS_ENABLE SDIO_CLKCTL_CLKBYP /*!< clock bypass */ + +/* SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLOCKPWRSAVE_DISABLE (uint32_t)0x00000000U /*!< SDIO_CLK clock is always on */ +#define SDIO_CLOCKPWRSAVE_ENABLE SDIO_CLKCTL_CLKPWRSAV /*!< SDIO_CLK closed when bus is idle */ + +/* SDIO command response type */ +#define CMDCTL_CMDRESP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define SDIO_RESPONSETYPE_NO CMDCTL_CMDRESP(0) /*!< no response */ +#define SDIO_RESPONSETYPE_SHORT CMDCTL_CMDRESP(1) /*!< short response */ +#define SDIO_RESPONSETYPE_LONG CMDCTL_CMDRESP(3) /*!< long response */ + +/* command state machine wait type */ +#define SDIO_WAITTYPE_NO (uint32_t)0x00000000U /*!< not wait interrupt */ +#define SDIO_WAITTYPE_INTERRUPT SDIO_CMDCTL_INTWAIT /*!< wait interrupt */ +#define SDIO_WAITTYPE_DATAEND SDIO_CMDCTL_WAITDEND /*!< wait the end of data transfer */ + +#define SDIO_RESPONSE0 (uint32_t)0x00000000U /*!< card response[31:0]/card response[127:96] */ +#define SDIO_RESPONSE1 (uint32_t)0x00000001U /*!< card response[95:64] */ +#define SDIO_RESPONSE2 (uint32_t)0x00000002U /*!< card response[63:32] */ +#define SDIO_RESPONSE3 (uint32_t)0x00000003U /*!< card response[31:1], plus bit 0 */ + +/* SDIO data block size */ +#define DATACTL_BLKSZ(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define SDIO_DATABLOCKSIZE_1BYTE DATACTL_BLKSZ(0) /*!< block size = 1 byte */ +#define SDIO_DATABLOCKSIZE_2BYTES DATACTL_BLKSZ(1) /*!< block size = 2 bytes */ +#define SDIO_DATABLOCKSIZE_4BYTES DATACTL_BLKSZ(2) /*!< block size = 4 bytes */ +#define SDIO_DATABLOCKSIZE_8BYTES DATACTL_BLKSZ(3) /*!< block size = 8 bytes */ +#define SDIO_DATABLOCKSIZE_16BYTES DATACTL_BLKSZ(4) /*!< block size = 16 bytes */ +#define SDIO_DATABLOCKSIZE_32BYTES DATACTL_BLKSZ(5) /*!< block size = 32 bytes */ +#define SDIO_DATABLOCKSIZE_64BYTES DATACTL_BLKSZ(6) /*!< block size = 64 bytes */ +#define SDIO_DATABLOCKSIZE_128BYTES DATACTL_BLKSZ(7) /*!< block size = 128 bytes */ +#define SDIO_DATABLOCKSIZE_256BYTES DATACTL_BLKSZ(8) /*!< block size = 256 bytes */ +#define SDIO_DATABLOCKSIZE_512BYTES DATACTL_BLKSZ(9) /*!< block size = 512 bytes */ +#define SDIO_DATABLOCKSIZE_1024BYTES DATACTL_BLKSZ(10) /*!< block size = 1024 bytes */ +#define SDIO_DATABLOCKSIZE_2048BYTES DATACTL_BLKSZ(11) /*!< block size = 2048 bytes */ +#define SDIO_DATABLOCKSIZE_4096BYTES DATACTL_BLKSZ(12) /*!< block size = 4096 bytes */ +#define SDIO_DATABLOCKSIZE_8192BYTES DATACTL_BLKSZ(13) /*!< block size = 8192 bytes */ +#define SDIO_DATABLOCKSIZE_16384BYTES DATACTL_BLKSZ(14) /*!< block size = 16384 bytes */ + +/* SDIO data transfer mode */ +#define SDIO_TRANSMODE_BLOCK (uint32_t)0x00000000U /*!< block transfer */ +#define SDIO_TRANSMODE_STREAM SDIO_DATACTL_TRANSMOD /*!< stream transfer or SDIO multibyte transfer */ + +/* SDIO data transfer direction */ +#define SDIO_TRANSDIRECTION_TOCARD (uint32_t)0x00000000U /*!< write data to card */ +#define SDIO_TRANSDIRECTION_TOSDIO SDIO_DATACTL_DATADIR /*!< read data from card */ + +/* SDIO read wait type */ +#define SDIO_READWAITTYPE_DAT2 (uint32_t)0x00000000U /*!< read wait control using SDIO_DAT[2] */ +#define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ + +/* function declarations */ +/* de/initialization functions, hardware clock, bus mode, power_state and SDIO clock configuration */ +/* deinitialize the SDIO */ +void sdio_deinit(void); +/* configure the SDIO clock */ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division); +/* enable hardware clock control */ +void sdio_hardware_clock_enable(void); +/* disable hardware clock control */ +void sdio_hardware_clock_disable(void); +/* set different SDIO card bus mode */ +void sdio_bus_mode_set(uint32_t bus_mode); +/* set the SDIO power state */ +void sdio_power_state_set(uint32_t power_state); +/* get the SDIO power state */ +uint32_t sdio_power_state_get(void); +/* enable SDIO_CLK clock output */ +void sdio_clock_enable(void); +/* disable SDIO_CLK clock output */ +void sdio_clock_disable(void); + +/* configure the command index, argument, response type, wait type and CSM to send command functions */ +/* configure the command and response */ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); +/* set the command state machine wait type */ +void sdio_wait_type_set(uint32_t wait_type); +/* enable the CSM(command state machine) */ +void sdio_csm_enable(void); +/* disable the CSM(command state machine) */ +void sdio_csm_disable(void); +/* get the last response command index */ +uint8_t sdio_command_index_get(void); +/* get the response for the last received command */ +uint32_t sdio_response_get(uint32_t responsex); + +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer functions */ +/* configure the data timeout, data length and data block size */ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); +/* configure the data transfer mode and direction */ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction); +/* enable the DSM(data state machine) for data transfer */ +void sdio_dsm_enable(void); +/* disable the DSM(data state machine) */ +void sdio_dsm_disable(void); +/* write data(one word) to the transmit FIFO */ +void sdio_data_write(uint32_t data); +/* read data(one word) from the receive FIFO */ +uint32_t sdio_data_read(void); +/* get the number of remaining data bytes to be transferred to card */ +uint32_t sdio_data_counter_get(void); +/* get the number of words remaining to be written or read from FIFO */ +uint32_t sdio_fifo_counter_get(void); +/* enable the DMA request for SDIO */ +void sdio_dma_enable(void); +/* disable the DMA request for SDIO */ +void sdio_dma_disable(void); + +/* flag and interrupt functions */ +/* get the flags state of SDIO */ +FlagStatus sdio_flag_get(uint32_t flag); +/* clear the pending flags of SDIO */ +void sdio_flag_clear(uint32_t flag); +/* enable the SDIO interrupt */ +void sdio_interrupt_enable(uint32_t int_flag); +/* disable the SDIO interrupt */ +void sdio_interrupt_disable(uint32_t int_flag); +/* get the interrupt flags state of SDIO */ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); +/* clear the interrupt pending flags of SDIO */ +void sdio_interrupt_flag_clear(uint32_t int_flag); + +/* SD I/O card functions */ +/* enable the read wait mode(SD I/O only) */ +void sdio_readwait_enable(void); +/* disable the read wait mode(SD I/O only) */ +void sdio_readwait_disable(void); +/* enable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_enable(void); +/* disable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_disable(void); +/* set the read wait type(SD I/O only) */ +void sdio_readwait_type_set(uint32_t readwait_type); +/* enable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_enable(void); +/* disable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_disable(void); +/* enable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_enable(void); +/* disable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_disable(void); + +/* CE-ATA functions */ +/* enable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_enable(void); +/* disable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_disable(void); +/* enable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_enable(void); +/* disable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_disable(void); +/* enable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_enable(void); +/* disable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_disable(void); + +#endif /* GD32F30X_SDIO_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h new file mode 100644 index 0000000000..44d691d07e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h @@ -0,0 +1,365 @@ +/*! + \file gd32f30x_spi.h + \brief definitions for the SPI + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_SPI_H +#define GD32F30X_SPI_H + +#include "gd32f30x.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ +#define SPI_QCTL(spix) REG32((spix) + 0x80U) /*!< SPI quad mode control register(only SPI0) */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3,5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_NSSP BIT(3) /*!< SPI NSS pulse mode enable */ +#define SPI_CTL1_TMOD BIT(4) /*!< SPI TI mode enable */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ +#define SPI_STAT_FERR BIT(8) /*!< format error bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR BITS(0,15) /*!< CRC polynomial register */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC register */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCR BITS(0,15) /*!< TX CRC register */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4,5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8,9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* SPI_QCTL(only for SPI0) */ +#define SPI_QCTL_QMOD BIT(0) /*!< quad-SPI mode enable */ +#define SPI_QCTL_QRD BIT(1) /*!< quad-SPI mode read select */ +#define SPI_QCTL_IO23_DRV BIT(2) /*!< drive SPI_IO2 and SPI_IO3 enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transtype */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by handware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescale factor */ +}spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by sofrware */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1,2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ +#define SPI_I2S_INT_FLAG_FERR ((uint8_t)0x06U) /*!< format error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define SPI_FLAG_FERR SPI_STAT_FERR /*!< format error flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_FERR SPI_STAT_FERR /*!< format error flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI struct with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* SPI DMA functions */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* SPI/I2S transfer configure functions */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* SPI TI mode functions */ +/* enable SPI TI mode */ +void spi_ti_mode_enable(uint32_t spi_periph); +/* disable SPI TI mode */ +void spi_ti_mode_disable(uint32_t spi_periph); + +/* SPI NSS pulse mode functions */ +/* enable SPI NSS pulse mode */ +void spi_nssp_mode_enable(uint32_t spi_periph); +/* disable SPI NSS pulse mode */ +void spi_nssp_mode_disable(uint32_t spi_periph); + +/* quad wire SPI functions */ +/* enable quad wire SPI */ +void qspi_enable(uint32_t spi_periph); +/* disable quad wire SPI */ +void qspi_disable(uint32_t spi_periph); +/* enable quad wire SPI write */ +void qspi_write_enable(uint32_t spi_periph); +/* enable quad wire SPI read */ +void qspi_read_enable(uint32_t spi_periph); +/* enable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_enable(uint32_t spi_periph); +/* disable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_disable(uint32_t spi_periph); + +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +#endif /* GD32F30X_SPI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h new file mode 100644 index 0000000000..7196b3a694 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h @@ -0,0 +1,752 @@ +/*! + \file gd32f30x_timer.h + \brief definitions for the TIMER + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_TIMER_H +#define GD32F30X_TIMER_H + +#include "gd32f30x.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) +#define TIMER7 (TIMER_BASE + 0x00013400U) +#define TIMER8 (TIMER_BASE + 0x00014C00U) +#define TIMER9 (TIMER_BASE + 0x00015000U) +#define TIMER10 (TIMER_BASE + 0x00015400U) +#define TIMER11 (TIMER_BASE + 0x00001800U) +#define TIMER12 (TIMER_BASE + 0x00001C00U) +#define TIMER13 (TIMER_BASE + 0x00002000U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER complementary channel protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ +#define TIMER_IRMP(timerx) REG32((timerx) + 0x50U) /*!< TIMER channel input remap register */ +#define TIMER_CFG(timerx) REG32((timerx) + 0xFCU) /*!< TIMER configuration register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5,6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0,2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4,6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8,11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 overcapture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 overcapture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 overcapture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 overcapture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0,1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4,6) /*!< channel 0 output compare mode */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8,9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12,14) /*!< channel 1 output compare mode */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2,3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4,7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10,11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12,15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0,1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4,6) /*!< channel 2 output compare mode */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8,9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12,14) /*!< channel 3 output compare mode */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2,3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4,7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10,11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0,15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0,15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0,15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0,7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8,9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0,4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8,12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0,15) /*!< DMA transfer buffer address */ + +/* TIMER_IRMP */ +#define TIMER10_IRMP_ITI1_RMP BITS(0,1) /*!< TIMER10 internal trigger input 1 remap */ + +/* TIMER_CFG */ +#define TIMER_CFG_OUTSEL BIT(0) /*!< the output value selection */ +#define TIMER_CFG_CHVSEL BIT(1) /*!< write CHxVAL register selection */ + +/* constants definitions */ +/* TIMER init parameter struct definitions*/ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint16_t clockdivision; /*!< clock division value */ + uint32_t period; /*!< period value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +}timer_parameter_struct; + +/* break parameter struct definitions*/ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +}timer_break_parameter_struct; + +/* channel output parameter struct definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +}timer_oc_parameter_struct; + +/* channel input parameter struct definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +}timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INTF_UPIF /*!< update interrupt flag */ +#define TIMER_INT_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 interrupt flag */ +#define TIMER_INT_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 interrupt flag */ +#define TIMER_INT_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 interrupt flag */ +#define TIMER_INT_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 interrupt flag */ +#define TIMER_INT_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger interrupt flag */ +#define TIMER_INT_FLAG_BRK TIMER_INTF_BRKIF + + + +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT ((uint8_t)0x00U) /*!< DMA request of channel y is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint8_t)0x01U) /*!< DMA request of channel y is sent when channel y event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA_DMATB DMACFG_DMATA(19) /*!< DMA transfer address is TIMER_DMATB */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW ((uint32_t)0x00000000U) /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000001U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE ((uint32_t)0x00000000U) /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000001U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR ((uint32_t)0x00000000U) /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000001U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals (CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4,7)) */ + +/* channel enable state*/ +#define TIMER_CCX_ENABLE ((uint32_t)0x00000001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint32_t)0x00000000U) /*!< channel disable */ + +/* channel complementary output enable state*/ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< timing mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< active mode */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< inactive mode */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle mode */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode*/ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers are updated when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI ((uint32_t)0x00000001U) /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ + +/* TIMER input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4*/ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channal0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE ((uint32_t)0x00000000U) /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000001U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000001U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0,1,2,13,14,15,16) write cc register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)0x0002U) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* the output value selection */ +#define TIMER_OUTSEL_ENABLE ((uint16_t)0x0001U) /*!< output value selection enable */ +#define TIMER_OUTSEL_DISABLE ((uint16_t)0x0000U) /*!< output value selection disable */ + + +/* function declarations */ +/* TIMER timebase */ +/* deinit a TIMER */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter struct */ +void timer_struct_para_init(timer_parameter_struct* initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +/* enable a TIMER */ +void timer_enable(uint32_t timer_periph); +/* disable a TIMER */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint8_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph , uint16_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* TIMER interrupt and flag*/ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get timer interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flags */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flags */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +/* timer DMA and event*/ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint8_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph,uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint8_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph,uint16_t channel, timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel,uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph,uint16_t channel,uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter struct */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph,uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity,uint32_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER configure */ +/* configure TIMER write CHxVAL register selection */ +void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel); +/* configure TIMER output value selection */ +void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel); + +#endif /* GD32F30X_TIMER_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h new file mode 100644 index 0000000000..2443676318 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h @@ -0,0 +1,444 @@ +/*! + \file gd32f30x_usart.h + \brief definitions for the USART + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_USART_H +#define GD32F30X_USART_H + +#include "gd32f30x.h" + +/* USARTx(x=0,1,2)/UARTx(x=3,4) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE+0x00000400U) /*!< USART2 base address */ +#define UART3 (USART_BASE+0x00000800U) /*!< UART3 base address */ +#define UART4 (USART_BASE+0x00000C00U) /*!< UART4 base address */ +#define USART0 (USART_BASE+0x0000F400U) /*!< USART0 base address */ + +/* registers definitions */ +#define USART_STAT0(usartx) REG32((usartx) + 0x00U) /*!< USART status register 0 */ +#define USART_DATA(usartx) REG32((usartx) + 0x04U) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + 0x08U) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + 0x0CU) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + 0x10U) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + 0x14U) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + 0x18U) /*!< USART guard time and prescaler register */ +#define USART_CTL3(usartx) REG32((usartx) + 0x80U) /*!< USART control register 3 */ +#define USART_RT(usartx) REG32((usartx) + 0x84U) /*!< USART receiver timeout register */ +#define USART_STAT1(usartx) REG32((usartx) + 0x88U) /*!< USART status register 1 */ + +/* bits definitions */ +/* USARTx_STAT0 */ +#define USART_STAT0_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT0_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT0_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT0_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT0_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT0_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT0_TC BIT(6) /*!< transmission complete */ +#define USART_STAT0_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT0_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT0_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + +/* USARTx_CTL3 */ +#define USART_CTL3_RTEN BIT(0) /*!< receiver timeout enable */ +#define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ +#define USART_CTL3_RTIE BIT(4) /*!< interrupt enable bit of receive timeout event */ +#define USART_CTL3_EBIE BIT(5) /*!< interrupt enable bit of end of block event */ +#define USART_CTL3_RINV BIT(8) /*!< RX pin level inversion */ +#define USART_CTL3_TINV BIT(9) /*!< TX pin level inversion */ +#define USART_CTL3_DINV BIT(10) /*!< data bit level inversion */ +#define USART_CTL3_MSBF BIT(11) /*!< most significant bit first */ + +/* USARTx_RT */ +#define USART_RT_RT BITS(0,23) /*!< receiver timeout threshold */ +#define USART_RT_BL BITS(24,31) /*!< block length */ + +/* USARTx_STAT1 */ +#define USART_STAT1_RTF BIT(11) /*!< receiver timeout flag */ +#define USART_STAT1_EBF BIT(12) /*!< end of block flag */ +#define USART_STAT1_BSY BIT(16) /*!< busy flag */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define USART_STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ +#define USART_STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ +#define USART_CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ +#define USART_CTL3_REG_OFFSET 0x80U /*!< CTL3 register offset */ + +/* USART flags */ +typedef enum +{ + /* flags in STAT0 register */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ + /* flags in STAT1 register */ + USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ + USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ + USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ +}usart_flag_enum; + +/* USART interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT0_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT0_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ + /* interrupt flags in CTL3 register */ + USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U), /*!< interrupt enable bit of end of block event and flag */ + USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U), /*!< interrupt enable bit of receive timeout event and flag */ +}usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ + /* interrupt in CTL3 register */ + USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U), /*!< end of block interrupt */ + USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U), /*!< receive timeout interrupt */ +}usart_interrupt_enum; + +/* USART invert configure */ +typedef enum +{ + /* data bit level inversion */ + USART_DINV_ENABLE, /*!< data bit level inversion */ + USART_DINV_DISABLE, /*!< data bit level not inversion */ + /* TX pin level inversion */ + USART_TXPIN_ENABLE, /*!< TX pin level inversion */ + USART_TXPIN_DISABLE, /*!< TX pin level not inversion */ + /* RX pin level inversion */ + USART_RXPIN_ENABLE, /*!< RX pin level inversion */ + USART_RXPIN_DISABLE, /*!< RX pin level not inversion */ +}usart_invert_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* USART data is transmitted/received with the LSB/MSB first */ +#define CTL3_MSBF(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_MSBF_LSB CTL3_MSBF(0) /*!< LSB first */ +#define USART_MSBF_MSB CTL3_MSBF(1) /*!< MSB first */ + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); + +/* USART normal mode communication */ +/* data is transmitted/received with the LSB/MSB first */ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf); +/* configure USART inverted */ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara); +/* enable receiver timeout */ +void usart_receiver_timeout_enable(uint32_t usart_periph); +/* disable receiver timeout */ +void usart_receiver_timeout_disable(uint32_t usart_periph); +/* configure receiver timeout threshold */ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint32_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* enable LIN mode */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* disable LIN mode */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* enable half-duplex mode */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* disable half-duplex mode */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* enable CK pin in synchronous mode */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* disable CK pin in synchronous mode */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* configure guard time value in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat); +/* enable smartcard mode */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* disable smartcard mode */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* enable NACK in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* disable NACK in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); +/* configure smartcard auto-retry number */ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum); +/* configure block length */ +void usart_block_length_config(uint32_t usart_periph, uint32_t bl); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* DMA communication */ +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* flag & interrupt functions */ +/* get flag in STAT0/STAT1 register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT0/STAT1 register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); +/* clear interrupt flag in STAT0/STAT1 register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); + +#endif /* GD32F30x_USART_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h new file mode 100644 index 0000000000..17c4738acf --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h @@ -0,0 +1,90 @@ +/*! + \file gd32f30x_wwdgt.h + \brief definitions for the WWDGT + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_WWDGT_H +#define GD32F30X_WWDGT_H + +#include "gd32f30x.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x04U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x08U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0,6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0,6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7,8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32F30X_WWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c new file mode 100644 index 0000000000..1374e23dc2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c @@ -0,0 +1,941 @@ +/*! + \file gd32f30x_adc.c + \brief ADC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_adc.h" + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + case ADC2: + rcu_periph_reset_enable(RCU_ADC2RST); + rcu_periph_reset_disable(RCU_ADC2RST); + break; +#endif + default: + break; + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while((ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while((ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief configure ADC resolution + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] resolution: ADC resolution + only one among these parameters can be selected + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph , uint32_t resolution) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one among these parameters can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel ,the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + ADC_CTL0(adc_periph) &= ~((uint32_t)( ADC_CTL0_DISRC | ADC_CTL0_DISIC )); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* config the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - 1U)); + + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + default: + break; + } +} + +/*! + \brief configure the ADC sync mode + \param[in] mode: ADC mode + only one among these parameters can be selected + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] function: the function to config + one or more parameters can be selected below + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (function & ADC_SCAN_MODE)){ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] data_alignment: data alignment select + only one parameter can be selected + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one parameter can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-1U)); + + break; + case ADC_INSERTED_CHANNEL: + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-1U)); + + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one among these parameters can be selected + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* ADC regular sequence config */ + if(rank < 6U){ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*rank))); + rsq |= ((uint32_t)adc_channel << (5U*rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < 12U){ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-6U)))); + rsq |= ((uint32_t)adc_channel << (5U*(rank-6U))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < 16U){ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-12U)))); + rsq |= ((uint32_t)adc_channel << (5U*(rank-12U))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + } + + /* ADC sampling time config */ + if(adc_channel < 10U){ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); + sampt |= (uint32_t)(sample_time << (3U*adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < 18U){ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); + sampt |= (uint32_t)(sample_time << (3U*(adc_channel-10U))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one among these parameters can be selected + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3 + rank) - inserted_length)))); + isq |= ((uint32_t)adc_channel << (5U * ((3 + rank) - inserted_length))); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < 10U){ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); + sampt |= (uint32_t) sample_time << (3U*adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < 18U){ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); + sampt |= ((uint32_t)sample_time << (3U*(adc_channel-10U))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel : insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted channel3 + \param[in] offset : the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + num = 3U - (inserted_length - inserted_channel); + + if(num <= 3U){ + /* calculate the offset of the register */ + num = num * 4U; + /* config the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief enable ADC external trigger + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one parameter can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: timer 0 CC0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: timer 0 CC1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: timer 1 CC1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: timer 2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: timer 3 CC3 event select + \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11 + \arg ADC2_EXTTRIG_REGULAR_T2_CH0: timer 2 CC0 event select + \arg ADC2_EXTTRIG_REGULAR_T1_CH2: timer 1 CC2 event select + \arg ADC2_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select + \arg ADC2_EXTTRIG_REGULAR_T7_CH0: timer 7 CC0 event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH0: timer 4 CC0 event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH2: timer 4 CC2 event select + \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: timer 1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: timer 1 CC0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: timer 2 CC3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: timer 3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select + \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select + \arg ADC2_EXTTRIG_INSERTED_T3_CH2: timer 3 CC2 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH1: timer 7 CC1 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select + \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: timer 4 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T4_CH3: timer 4 CC3 event select + \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel : insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + only one parameter can be selected + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the ADC interrupt bits + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt bits + only oneparameter can be selected + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + return interrupt_flag; +} + +/*! + \brief clear the ADC flag + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt) +{ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel: the selected ADC channel + only one among these parameters can be selected + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] low_threshold: analog watchdog low threshold,0..4095 + \param[in] high_threshold: analog watchdog high threshold,0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief configure ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] mode: ADC oversampling mode + only oneparameter can be selected + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger + \param[in] shift: ADC oversampling shift + only oneparameter can be selected + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only oneparameter can be selected + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio) +{ + if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; + }else{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + } + /* config the shift and ratio */ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); + ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c new file mode 100644 index 0000000000..3aeab280e2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c @@ -0,0 +1,328 @@ +/*! + \file gd32f30x_bkp.c + \brief BKP driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_bkp.h" + +#define TAMPER_FLAG_SHIFT ((uint8_t)8U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum, only one parameter can be selected + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_write_data(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number-1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number-1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum, only one parameter can be selected + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_read_data(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number-1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number-1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief select RTC clock output + \param[in] clocksel: RTC clock output selection + \arg RTC_CLOCK_DIV_64: RTC clock div 64 + \arg RTC_CLOCK_DIV_1: RTC clock + \param[out] none + \retval none +*/ +void bkp_rtc_clock_output_select(uint16_t clocksel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CCOSEL; + ctl |= clocksel; + BKP_OCTL = ctl; +} + +/*! + \brief RTC clock calibration direction + \param[in] direction: RTC clock calibration direction + \arg RTC_CLOCK_SLOWED_DOWN: RTC clock slow down + \arg RTC_CLOCK_SPEED_UP: RTC clock speed up + \param[out] none + \retval none +*/ +void bkp_rtc_clock_calibration_direction(uint16_t direction) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CALDIR; + ctl |= direction; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + ctl = BKP_OCTL; + ctl &= ~(uint16_t)BKP_OCTL_RCCV; + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(void) +{ + BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN; +} + +/*! + \brief disable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(void) +{ + BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN; +} + +/*! + \brief set tamper pin active level + \param[in] level: tamper active level + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(uint16_t level) +{ + uint16_t ctl = 0U; + + ctl = BKP_TPCTL; + ctl &= (uint16_t)~BKP_TPCTL_TPAL; + ctl |= level; + BKP_TPCTL = ctl; +} + +/*! + \brief enable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_enable(void) +{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE; +} + +/*! + \brief disable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_disable(void) +{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE; +} + +/*! + \brief get bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER: tamper event flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER: tamper event flag + \param[out] none + \retval none +*/ +void bkp_flag_clear(uint16_t flag) +{ + BKP_TPCS |= (uint16_t)(flag >> TAMPER_FLAG_SHIFT); +} + +/*! + \brief get bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER: tamper interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER: tamper interrupt flag + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(uint16_t flag) +{ + BKP_TPCS |= (uint16_t)(flag >> TAMPER_FLAG_SHIFT); +} + diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c new file mode 100644 index 0000000000..e26e5df00a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c @@ -0,0 +1,1042 @@ +/*! + \file gd32f30x_can.c + \brief CAN driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-11-27, V2.0.1, firmware for GD32F30x + \version 2020-03-02, V2.0.2, firmware for GD32F30x + \version 2020-07-14, V2.0.3, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_can.h" +#include + +#define CAN_ERROR_HANDLE(s) do{}while(1) + +/*! + \brief deinitialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_deinit(uint32_t can_periph) +{ +#ifdef GD32F30X_CL + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + }else{ + rcu_periph_reset_enable(RCU_CAN1RST); + rcu_periph_reset_disable(RCU_CAN1RST); + } +#else + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + } +#endif +} + +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + if(NULL == p_struct){ + CAN_ERROR_HANDLE("struct parameter can not be NULL \r\n"); + } + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + +/*! + \brief initialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init) +{ + uint32_t timeout = CAN_TIMEOUT; + ErrStatus flag = ERROR; + + /* disable sleep mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + /* enable initialize mode */ + CAN_CTL(can_periph) |= CAN_CTL_IWMOD; + /* wait ACK */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check initialize working success */ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + /* set the bit timing register */ + CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ + BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ + BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ + BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ + BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + + /* time trigger communication mode */ + if(ENABLE == can_parameter_init->time_triggered){ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + } + /* automatic bus-off managment */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + CAN_CTL(can_periph) |= CAN_CTL_ABOR; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; + } + /* automatic wakeup mode */ + if(ENABLE == can_parameter_init->auto_wake_up){ + CAN_CTL(can_periph) |= CAN_CTL_AWU; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_AWU; + } + /* automatic retransmission mode disable */ + if(ENABLE == can_parameter_init->no_auto_retrans){ + CAN_CTL(can_periph) |= CAN_CTL_ARD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite){ + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; + } + /* transmit fifo order */ + if(ENABLE == can_parameter_init->trans_fifo_order){ + CAN_CTL(can_periph) |= CAN_CTL_TFO; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TFO; + } + /* disable initialize mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; + timeout = CAN_TIMEOUT; + /* wait the ACK */ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check exit initialize mode */ + if(0U != timeout){ + flag = SUCCESS; + } + } + return flag; +} + +/*! + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +{ + uint32_t val = 0U; + + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* disable filter */ + CAN_FW(CAN0) &= ~(uint32_t)val; + + /* filter 16 bits */ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + /* set filter 16 bits */ + CAN_FSCFG(CAN0) &= ~(uint32_t)val; + /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + } + /* filter 32 bits */ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + /* set filter 32 bits */ + CAN_FSCFG(CAN0) |= (uint32_t)val; + /* 32 bits list or first 32 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* 32 bits mask or second 32 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + } + + /* filter mode */ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + /* mask mode */ + CAN_FMCFG(CAN0) &= ~(uint32_t)val; + }else{ + /* list mode */ + CAN_FMCFG(CAN0) |= (uint32_t)val; + } + + /* filter FIFO */ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + /* FIFO0 */ + CAN_FAFIFO(CAN0) &= ~(uint32_t)val; + }else{ + /* FIFO1 */ + CAN_FAFIFO(CAN0) |= (uint32_t)val; + } + + /* filter working */ + if(ENABLE == can_filter_parameter_init->filter_enable){ + + CAN_FW(CAN0) |= (uint32_t)val; + } + + /* filter lock enable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief set CAN1 fliter start bank number + \param[in] start_bank: CAN1 start bank number + only one parameter can be selected which is shown as below: + \arg (1..27) + \param[out] none + \retval none +*/ +void can1_filter_start_bank(uint8_t start_bank) +{ + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* set CAN1 filter start number */ + CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; + CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); + /* filter lock enaable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief enable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_enable(uint32_t can_periph) +{ + CAN_CTL(can_periph) |= CAN_CTL_DFZ; +#ifdef GD32F30X_CL + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + }else{ + dbg_periph_enable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief disable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_disable(uint32_t can_periph) +{ + CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; +#ifdef GD32F30X_CL + if(CAN0 == can_periph){ + dbg_periph_disable(DBG_CAN0_HOLD); + }else{ + dbg_periph_disable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief enable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_enable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* enable the tcc mode */ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + /* enable time stamp */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; + } +} + +/*! + \brief disable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_disable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* disable the TCC mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + /* reset TSEN bits */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; + } +} + +/*! + \brief transmit CAN message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF + \param[out] none + \retval mailbox_number +*/ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +{ + uint8_t mailbox_number = CAN_MAILBOX0; + + /* select one empty mailbox */ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + mailbox_number = CAN_MAILBOX0; + }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + mailbox_number = CAN_MAILBOX1; + }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + mailbox_number = CAN_MAILBOX2; + }else{ + mailbox_number = CAN_NOMAILBOX; + } + /* return no mailbox empty */ + if(CAN_NOMAILBOX == mailbox_number){ + return CAN_NOMAILBOX; + } + + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; + if(CAN_FF_STANDARD == transmit_message->tx_ff){ + /* set transmit mailbox standard identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ + transmit_message->tx_ft); + }else{ + /* set transmit mailbox extended identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ + transmit_message->tx_ff | \ + transmit_message->tx_ft); + } + /* set the data length */ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; + CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; + /* set the data */ + CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); + CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); + /* enable transmission */ + CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; + + return mailbox_number; +} + +/*! + \brief get CAN transmit state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOX(x=0,1,2) + \param[out] none + \retval can_transmit_state_enum +*/ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) +{ + can_transmit_state_enum state = CAN_TRANSMIT_FAILED; + uint32_t val = 0U; + + /* check selected mailbox state */ + switch(mailbox_number){ + /* mailbox0 */ + case CAN_MAILBOX0: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); + break; + /* mailbox1 */ + case CAN_MAILBOX1: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); + break; + /* mailbox2 */ + case CAN_MAILBOX2: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); + break; + default: + val = CAN_TRANSMIT_FAILED; + break; + } + + switch(val){ + /* transmit pending */ + case (CAN_STATE_PENDING): + state = CAN_TRANSMIT_PENDING; + break; + /* mailbox0 transmit succeeded */ + case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + state = CAN_TRANSMIT_OK; + break; + /* mailbox1 transmit succeeded */ + case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + state = CAN_TRANSMIT_OK; + break; + /* mailbox2 transmit succeeded */ + case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + state = CAN_TRANSMIT_OK; + break; + /* transmit failed */ + default: + state = CAN_TRANSMIT_FAILED; + break; + } + return state; +} + +/*! + \brief stop CAN transmission + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOXx(x=0,1,2) + \param[out] none + \retval none +*/ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) +{ + if(CAN_MAILBOX0 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } + }else if(CAN_MAILBOX1 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } + }else if(CAN_MAILBOX2 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } + }else{ + /* illegal parameters */ + } +} + +/*! + \brief CAN receive message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] fifo_number + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 + \retval none +*/ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +{ + /* get the frame format */ + receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); + if(CAN_FF_STANDARD == receive_message->rx_ff){ + /* get standard identifier */ + receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + }else{ + /* get extended identifier */ + receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + } + + /* get frame type */ + receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); + /* filtering index */ + receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + /* get recevie data length */ + receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + + /* receive data */ + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + + /* release FIFO */ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else{ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + } +} + +/*! + \brief release FIFO0 + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval none +*/ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) +{ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else if(CAN_FIFO1 == fifo_number){ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + }else{ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); + } +} + +/*! + \brief CAN receive message length + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval message length +*/ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) +{ + uint8_t val = 0U; + + if(CAN_FIFO0 == fifo_number){ + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); + }else{ + /* illegal parameters */ + } + return val; +} + +/*! + \brief set CAN working mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] can_working_mode + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) +{ + ErrStatus flag = ERROR; + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode){ + /* disable sleep mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); + /* set initialize mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; + /* wait the acknowledge */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_NORMAL == working_mode){ + /* enter normal mode */ + CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); + /* wait the acknowledge */ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + timeout--; + } + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_SLEEP == working_mode){ + /* disable initialize mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); + /* set sleep mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; + /* wait the acknowledge */ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else{ + flag = ERROR; + } + return flag; +} + +/*! + \brief wake up CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_wakeup(uint32_t can_periph) +{ + ErrStatus flag = ERROR; + uint32_t timeout = CAN_TIMEOUT; + + /* wakeup */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + timeout--; + } + /* check state */ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + return flag; +} + +/*! + \brief get CAN error type + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure +*/ +can_error_enum can_error_get(uint32_t can_periph) +{ + can_error_enum error; + error = CAN_ERROR_NONE; + + /* get error type */ + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); + return error; +} + +/*! + \brief get CAN receive error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval error number +*/ +uint8_t can_receive_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief get CAN transmit error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval error number +*/ +uint8_t can_transmit_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + +/*! + \brief get CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) +{ + /* get flag and interrupt enable state */ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \param[out] none + \retval none +*/ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag) +{ + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); +} + +/*! + \brief get CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFL0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFL1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); + } + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \param[out] none + \retval none +*/ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c new file mode 100644 index 0000000000..c3b961fca8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c @@ -0,0 +1,130 @@ +/*! + \file gd32f30x_crc.c + \brief CRC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specified 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(const uint32_t *array, uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = *(array+index); + } + return (CRC_DATA); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c new file mode 100644 index 0000000000..ac20e8f46c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c @@ -0,0 +1,393 @@ +/*! + \file gd32f30x_ctc.c + \brief CTC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_ctc.h" + +#define CTC_FLAG_MASK ((uint32_t)0x00000700U) + +/* CTC register bit offset */ +#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U) +#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U) +#define CTC_REFCAP_OFFSET ((uint32_t)16U) +#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U) + +/*! + \brief reset CTC clock trim controller + \param[in] none + \param[out] none + \retval none +*/ +void ctc_deinit(void) +{ + /* reset CTC */ + rcu_periph_reset_enable(RCU_CTCRST); + rcu_periph_reset_disable(RCU_CTCRST); +} + + + +/*! + \brief enable CTC trim counter + \param[in] none + \param[out] none + \retval none +*/ +void ctc_counter_enable(void) +{ + CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN; +} + +/*! + \brief disable CTC trim counter + \param[in] none + \param[out] none + \retval none +*/ +void ctc_counter_disable(void) +{ + CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN); +} + +/*! + \brief configure the IRC48M trim value + \param[in] ctc_trim_value: 8-bit IRC48M trim value + \arg 0x00 - 0x3F + \param[out] none + \retval none +*/ +void ctc_irc48m_trim_value_config(uint8_t trim_value) +{ + /* clear TRIMVALUE bits */ + CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE); + /* set TRIMVALUE bits */ + CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET); +} + +/*! + \brief generate software reference source sync pulse + \param[in] none + \param[out] none + \retval none +*/ +void ctc_software_refsource_pulse_generate(void) +{ + CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL; +} + +/*! + \brief configure hardware automatically trim mode + \param[in] hardmode: + only one parameter can be selected which is shown as below: + \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable + \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable + \param[out] none + \retval none +*/ +void ctc_hardware_trim_mode_config(uint32_t hardmode) +{ + CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM); + CTC_CTL0 |= (uint32_t)hardmode; +} +/*! + \brief configure reference signal source polarity + \param[in] polarity: + only one parameter can be selected which is shown as below: + \arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge + \arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge + \param[out] none + \retval none +*/ +void ctc_refsource_polarity_config(uint32_t polarity) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL); + CTC_CTL1 |= (uint32_t)polarity; +} + +/*! + \brief select reference signal source + \param[in] refs: + only one parameter can be selected which is shown as below: + \arg CTC_REFSOURCE_GPIO: GPIO is selected + \arg CTC_REFSOURCE_LXTAL: LXTAL is selected + \arg CTC_REFSOURCE_USBSOF: USBD_SOF or USBFS_SOF is selected + \param[out] none + \retval none +*/ +void ctc_refsource_signal_select(uint32_t refs) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL); + CTC_CTL1 |= (uint32_t)refs; +} + +/*! + \brief configure reference signal source prescaler + \param[in] prescaler: + only one parameter can be selected which is shown as below: + \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided + \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2 + \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4 + \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8 + \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16 + \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32 + \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64 + \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128 + \param[out] none + \retval none +*/ +void ctc_refsource_prescaler_config(uint32_t prescaler) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC); + CTC_CTL1 |= (uint32_t)prescaler; +} + +/*! + \brief configure clock trim base limit value + \param[in] limit_value: 8-bit clock trim base limit value + \arg 0x00 - 0xFF + \param[out] none + \retval none +*/ +void ctc_clock_limit_value_config(uint8_t limit_value) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM); + CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET); +} + +/*! + \brief configure CTC counter reload value + \param[in] reload_value: 16-bit CTC counter reload value + \arg 0x0000 - 0xFFFF + \param[out] none + \retval none +*/ +void ctc_counter_reload_value_config(uint16_t reload_value) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE); + CTC_CTL1 |= (uint32_t)reload_value; +} + +/*! + \brief read CTC counter capture value when reference sync pulse occurred + \param[in] none + \param[out] none + \retval the 16-bit CTC counter capture value +*/ +uint16_t ctc_counter_capture_value_read(void) +{ + uint16_t capture_value = 0U; + capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET); + return (capture_value); +} + +/*! + \brief read CTC trim counter direction when reference sync pulse occurred + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET + \arg SET: CTC trim counter direction is down-counting + \arg RESET: CTC trim counter direction is up-counting +*/ +FlagStatus ctc_counter_direction_read(void) +{ + if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief read CTC counter reload value + \param[in] none + \param[out] none + \retval the 16-bit CTC counter reload value +*/ +uint16_t ctc_counter_reload_value_read(void) +{ + uint16_t reload_value = 0U; + reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE); + return (reload_value); +} + +/*! + \brief read the IRC48M trim value + \param[in] none + \param[out] none + \retval the 8-bit IRC48M trim value +*/ +uint8_t ctc_irc48m_trim_value_read(void) +{ + uint8_t trim_value = 0U; + trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET); + return (trim_value); +} + +/*! + \brief enable the CTC interrupt + \param[in] interrupt: CTC interrupt enable + one or more parameters can be selected which are shown as below: + \arg CTC_INT_CKOK: clock trim OK interrupt enable + \arg CTC_INT_CKWARN: clock trim warning interrupt enable + \arg CTC_INT_ERR: error interrupt enable + \arg CTC_INT_EREF: expect reference interrupt enable + \param[out] none + \retval none +*/ +void ctc_interrupt_enable(uint32_t interrupt) +{ + CTC_CTL0 |= (uint32_t)interrupt; +} + +/*! + \brief disable the CTC interrupt + \param[in] interrupt: CTC interrupt enable source + one or more parameters can be selected which are shown as below: + \arg CTC_INT_CKOK: clock trim OK interrupt enable + \arg CTC_INT_CKWARN: clock trim warning interrupt enable + \arg CTC_INT_ERR: error interrupt enable + \arg CTC_INT_EREF: expect reference interrupt enable + \param[out] none + \retval none +*/ +void ctc_interrupt_disable(uint32_t interrupt) +{ + CTC_CTL0 &= (uint32_t)(~interrupt); +} + +/*! + \brief get CTC interrupt flag + \param[in] int_flag: the CTC interrupt flag + only one parameter can be selected which is shown as below: + \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt + \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt + \arg CTC_INT_FLAG_ERR: error interrupt + \arg CTC_INT_FLAG_EREF: expect reference interrupt + \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt + \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt + \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ctc_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t interrupt_flag = 0U, intenable = 0U; + + /* check whether the interrupt is enabled */ + if(RESET != (int_flag & CTC_FLAG_MASK)){ + intenable = CTC_CTL0 & CTC_CTL0_ERRIE; + }else{ + intenable = CTC_CTL0 & int_flag; + } + + /* get interrupt flag status */ + interrupt_flag = CTC_STAT & int_flag; + + if(interrupt_flag && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CTC interrupt flag + \param[in] int_flag: the CTC interrupt flag + only one parameter can be selected which is shown as below: + \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt + \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt + \arg CTC_INT_FLAG_ERR: error interrupt + \arg CTC_INT_FLAG_EREF: expect reference interrupt + \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt + \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt + \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt + \param[out] none + \retval none +*/ +void ctc_interrupt_flag_clear(uint32_t int_flag) +{ + if(RESET != (int_flag & CTC_FLAG_MASK)){ + CTC_INTC |= CTC_INTC_ERRIC; + }else{ + CTC_INTC |= int_flag; + } +} + +/*! + \brief get CTC flag + \param[in] flag: the CTC flag + only one parameter can be selected which is shown as below: + \arg CTC_FLAG_CKOK: clock trim OK flag + \arg CTC_FLAG_CKWARN: clock trim warning flag + \arg CTC_FLAG_ERR: error flag + \arg CTC_FLAG_EREF: expect reference flag + \arg CTC_FLAG_CKERR: clock trim error bit + \arg CTC_FLAG_REFMISS: reference sync pulse miss + \arg CTC_FLAG_TRIMERR: trim value error bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ctc_flag_get(uint32_t flag) +{ + if(RESET != (CTC_STAT & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CTC flag + \param[in] flag: the CTC flag + only one parameter can be selected which is shown as below: + \arg CTC_FLAG_CKOK: clock trim OK flag + \arg CTC_FLAG_CKWARN: clock trim warning flag + \arg CTC_FLAG_ERR: error flag + \arg CTC_FLAG_EREF: expect reference flag + \arg CTC_FLAG_CKERR: clock trim error bit + \arg CTC_FLAG_REFMISS: reference sync pulse miss + \arg CTC_FLAG_TRIMERR: trim value error bit + \param[out] none + \retval none +*/ +void ctc_flag_clear(uint32_t flag) +{ + if(RESET != (flag & CTC_FLAG_MASK)){ + CTC_INTC |= CTC_INTC_ERRIC; + }else{ + CTC_INTC |= flag; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c new file mode 100644 index 0000000000..55a53f75ab --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c @@ -0,0 +1,541 @@ +/*! + \file gd32f30x_dac.c + \brief DAC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_dac.h" + +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + +/*! + \brief deinitialize DAC + \param[in] none + \param[out] none + \retval none +*/ +void dac_deinit(void) +{ + rcu_periph_reset_enable(RCU_DACRST); + rcu_periph_reset_disable(RCU_DACRST); +} + +/*! + \brief enable DAC + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DEN0; + }else{ + DAC_CTL |= DAC_CTL_DEN1; + } +} + +/*! + \brief disable DAC + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DEN1; + } +} + +/*! + \brief enable DAC DMA function + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_dma_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DDMAEN0; + }else{ + DAC_CTL |= DAC_CTL_DDMAEN1; + } +} + +/*! + \brief disable DAC DMA function + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_dma_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDMAEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DDMAEN1; + } +} + +/*! + \brief enable DAC output buffer + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DBOFF0; + }else{ + DAC_CTL &= ~DAC_CTL_DBOFF1; + } +} + +/*! + \brief disable DAC output buffer + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DBOFF0; + }else{ + DAC_CTL |= DAC_CTL_DBOFF1; + } +} + +/*! + \brief get DAC output value + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph: DACx(x = 0,1) + \param[in] dac_align: data alignment + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8 bit alignment + \arg DAC_ALIGN_12B_R: data right 12 bit alignment + \arg DAC_ALIGN_12B_L: data left 12 bit alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12 bit alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12 bit alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8 bit alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12 bit alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12 bit alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8 bit alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + +/*! + \brief enable DAC trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DTEN0; + }else{ + DAC_CTL |= DAC_CTL_DTEN1; + } +} + +/*! + \brief disable DAC trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DTEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DTEN1; + } +} + +/*! + \brief set DAC trigger source + \param[in] dac_periph: DACx(x = 0,1) + \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: + \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO + \arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO (for GD32F30X_CL) + \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO + \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO + \arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO + \arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO + \arg DAC_TRIGGER_T7_TRGO: TIMER7 TRGO (for GD32F30X_HD and GD32F30X_XD) + \arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event + \arg DAC_TRIGGER_SOFTWARE: software trigger + \param[out] none + \retval none +*/ +void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL0; + DAC_CTL |= triggersource; + }else{ + /* configure DAC1 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL1; + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph: DACx(x = 0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; + } +} + +/*! + \brief configure DAC wave mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] wave_mode: noise wave mode + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_DISABLE: wave disable + \arg DAC_WAVE_MODE_LFSR: LFSR noise mode + \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode + \param[out] none + \retval none +*/ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM0; + DAC_CTL |= wave_mode; + }else{ + /* configure DAC1 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM1; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC wave bit width + \param[in] dac_periph: DACx(x = 0,1) + \param[in] bit_width: noise wave bit width + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 + \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 + \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 + \arg DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4 + \arg DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5 + \arg DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6 + \arg DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7 + \arg DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8 + \arg DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9 + \arg DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10 + \arg DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11 + \arg DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12 + \param[out] none + \retval none +*/ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= bit_width; + }else{ + /* configure DAC1 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC LFSR noise mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] unmask_bits: unmask LFSR bits in DAC LFSR noise mode + only one parameter can be selected which is shown as below: + \arg DAC_LFSR_BIT0: unmask the LFSR bit0 + \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] + \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] + \arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0] + \arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0] + \arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0] + \arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0] + \arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0] + \arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0] + \arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0] + \arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0] + \arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0] + \param[out] none + \retval none +*/ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= unmask_bits; + }else{ + /* configure DAC1 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC triangle noise mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] amplitude: triangle amplitude in DAC triangle noise mode + only one parameter can be selected which is shown as below: + \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 + \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 + \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 + \arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15 + \arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31 + \arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63 + \arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127 + \arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255 + \arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511 + \arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023 + \arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047 + \arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095 + \param[out] none + \retval none +*/ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= amplitude; + }else{ + /* configure DAC1 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL |= (ctl); +} + +/*! + \brief disable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL &= (~ctl); +} + +/*! + \brief enable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_enable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT |= (swt); +} + +/*! + \brief disable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_disable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT &= (~swt); +} + +/*! + \brief enable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL &= (~ctl); +} + +/*! + \brief disable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL |= (ctl); +} + +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align: data alignment + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c new file mode 100644 index 0000000000..8cae11f6ce --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c @@ -0,0 +1,164 @@ +/*! + \file gd32f30x_dbg.c + \brief DBG driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_dbg.h" + +#define DBG_RESET_VAL 0x00000000U + +/*! + \brief deinitialize the DBG + \param[in] none + \param[out] none + \retval none +*/ +void dbg_deinit(void) +{ + DBG_CTL0 = DBG_RESET_VAL; +} + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + this parameter can be any combination of the following values: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL0 |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + this parameter can be any combination of the following values: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL0 &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + only one parameter can be selected which is shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph)); +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + only one parameter can be selected which is shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_REG_VAL(dbg_periph) &= ~BIT(DBG_BIT_POS(dbg_periph)); +} + +/*! + \brief enable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_enable(void) +{ + DBG_CTL0 |= DBG_CTL0_TRACE_IOEN; +} + +/*! + \brief disable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_disable(void) +{ + DBG_CTL0 &= ~DBG_CTL0_TRACE_IOEN; +} + +/*! + \brief trace pin mode selection + \param[in] trace_mode: + \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 + \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 + \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 + \param[out] none + \retval none +*/ +void dbg_trace_pin_mode_set(uint32_t trace_mode) +{ + DBG_CTL0 &= ~DBG_CTL0_TRACE_MODE; + DBG_CTL0 |= trace_mode; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c new file mode 100644 index 0000000000..342025c5d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c @@ -0,0 +1,735 @@ +/*! + \file gd32f30x_dma.c + \brief DMA driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_dma.h" +#include + +#define DMA_WRONG_HANDLE while(1){} + +/* check whether peripheral matches channels or not */ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx); + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* disable DMA a channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + if(NULL == init_struct){ + DMA_WRONG_HANDLE + } + + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width and priority */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] number: the number of remaining data to be transferred by the DMA + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + } else { + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + + switch(flag){ + case DMA_INT_FLAG_FTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + default: + DMA_WRONG_HANDLE + } + + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief check whether peripheral and channels match + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx) +{ + ErrStatus val = SUCCESS; + + if(DMA1 == dma_periph){ + /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */ + if(channelx > DMA_CH4){ + val = ERROR; + } + } + + return val; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c new file mode 100644 index 0000000000..78d82a99a4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c @@ -0,0 +1,3680 @@ +/*! + \file gd32f30x_enet.c + \brief ENET driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-04-02, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_enet.h" +#include + +#ifdef GD32F30X_CL + +#if defined (__CC_ARM) /*!< ARM compiler */ +__align(4) +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +__align(4) +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +__align(4) +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +__align(4) +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined ( __ICCARM__ ) /*!< IAR compiler */ +#pragma data_alignment=4 +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +#pragma data_alignment=4 +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +#pragma data_alignment=4 +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +#pragma data_alignment=4 +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ + +#endif /* __CC_ARM */ + +/* global transmit and receive descriptors pointers */ +enet_descriptors_struct *dma_current_txdesc; +enet_descriptors_struct *dma_current_rxdesc; + +/* structure pointer of ptp descriptor for normal mode */ +enet_descriptors_struct *dma_current_ptp_txdesc = NULL; +enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; + +/* init structure parameters for ENET initialization */ +static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static uint32_t enet_unknow_err = 0U; +/* array of register offset for debug information get */ +static const uint16_t enet_reg_tab[] = { +0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0028, 0x002C, 0x0034, +0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x1080, + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, 0x0728, 0x072C, + +0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1024, 0x1048, +0x104C, 0x1050, 0x1054}; + +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); + +#ifndef USE_DELAY +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +#endif /* USE_DELAY */ + +/*! + \brief deinitialize the ENET, and reset structure parameters for ENET initialization + \param[in] none + \param[out] none + \retval none +*/ +void enet_deinit(void) +{ + rcu_periph_reset_enable(RCU_ENETRST); + rcu_periph_reset_disable(RCU_ENETRST); + enet_initpara_reset(); +} + +/*! + \brief configure the parameters which are usually less cared for initialization + note -- this function must be called before enet_init(), otherwise + configuration will be no effect + \param[in] option: different function option, which is related to several parameters, + only one parameter can be selected which is shown as below, refer to enet_option_enum + \arg FORWARD_OPTION: choose to configure the frame forward related parameters + \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters + \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters + \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters + \arg STORE_OPTION: choose to configure the store forward mode related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg VLAN_OPTION: choose to configure vlan related parameters + \arg FLOWCTL_OPTION: choose to configure flow control related parameters + \arg HASHH_OPTION: choose to configure hash high + \arg HASHL_OPTION: choose to configure hash low + \arg FILTER_OPTION: choose to configure frame filter related parameters + \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters + \arg TIMER_OPTION: choose to configure time counter related parameters + \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below + FORWARD_OPTION related parameters: + - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; + - ENET_TYPEFRAME_CRC_DROP_ENABLE/ ENET_TYPEFRAME_CRC_DROP_DISABLE ; + - ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ; + - ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE . + DMABUS_OPTION related parameters: + - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; + - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; + - ENET_MIXED_BURST_ENABLE/ ENET_MIXED_BURST_DISABLE ; + DMA_MAXBURST_OPTION related parameters: + - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ + ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ + ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/ + ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/ + ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ; + - ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/ + ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/ + ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/ + ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/ + ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ; + - ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ; + DMA_ARBITRATION_OPTION related parameters: + - ENET_ARBITRATION_RXPRIORTX + - ENET_ARBITRATION_RXTX_1_1/ ENET_ARBITRATION_RXTX_2_1/ + ENET_ARBITRATION_RXTX_3_1/ ENET_ARBITRATION_RXTX_4_1/. + STORE_OPTION related parameters: + - ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ; + - ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ; + - ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/ + ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ; + - ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/ + ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/ + ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/ + ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES . + DMA_OPTION related parameters: + - ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ; + - ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE ; + - ENET_ENHANCED_DESCRIPTOR/ ENET_NORMAL_DESCRIPTOR . + VLAN_OPTION related parameters: + - ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ; + - MAC_VLT_VLTI(regval) . + FLOWCTL_OPTION related parameters: + - MAC_FCTL_PTM(regval) ; + - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; + - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; + - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; + - ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE ; + - ENET_ACTIVE_THRESHOLD_256BYTES/ ENET_ACTIVE_THRESHOLD_512BYTES ; + - ENET_ACTIVE_THRESHOLD_768BYTES/ ENET_ACTIVE_THRESHOLD_1024BYTES ; + - ENET_ACTIVE_THRESHOLD_1280BYTES/ ENET_ACTIVE_THRESHOLD_1536BYTES ; + - ENET_ACTIVE_THRESHOLD_1792BYTES ; + - ENET_DEACTIVE_THRESHOLD_256BYTES/ ENET_DEACTIVE_THRESHOLD_512BYTES ; + - ENET_DEACTIVE_THRESHOLD_768BYTES/ ENET_DEACTIVE_THRESHOLD_1024BYTES ; + - ENET_DEACTIVE_THRESHOLD_1280BYTES/ ENET_DEACTIVE_THRESHOLD_1536BYTES ; + - ENET_DEACTIVE_THRESHOLD_1792BYTES . + HASHH_OPTION related parameters: + - 0x0~0xFFFF FFFFU + HASHL_OPTION related parameters: + - 0x0~0xFFFF FFFFU + FILTER_OPTION related parameters: + - ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/ + ENET_SRC_FILTER_DISABLE ; + - ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ; + - ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/ + ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ; + - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ + ENET_UNICAST_FILTER_PERFECT ; + - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + HALFDUPLEX_OPTION related parameters: + - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; + - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; + - ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ; + - ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/ + ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ; + - ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE . + TIMER_OPTION related parameters: + - ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ; + - ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ; + INTERFRAMEGAP_OPTION related parameters: + - ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/ + ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ + ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ + ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . + \param[out] none + \retval none +*/ +void enet_initpara_config(enet_option_enum option, uint32_t para) +{ + switch(option){ + case FORWARD_OPTION: + /* choose to configure forward_frame, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; + enet_initpara.forward_frame = para; + break; + case DMABUS_OPTION: + /* choose to configure dmabus_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION; + enet_initpara.dmabus_mode = para; + break; + case DMA_MAXBURST_OPTION: + /* choose to configure dma_maxburst, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION; + enet_initpara.dma_maxburst = para; + break; + case DMA_ARBITRATION_OPTION: + /* choose to configure dma_arbitration, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION; + enet_initpara.dma_arbitration = para; + break; + case STORE_OPTION: + /* choose to configure store_forward_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)STORE_OPTION; + enet_initpara.store_forward_mode = para; + break; + case DMA_OPTION: + /* choose to configure dma_function, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_OPTION; + +#ifndef SELECT_DESCRIPTORS_ENHANCED_MODE + para &= ~ENET_ENHANCED_DESCRIPTOR; +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + + enet_initpara.dma_function = para; + break; + case VLAN_OPTION: + /* choose to configure vlan_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)VLAN_OPTION; + enet_initpara.vlan_config = para; + break; + case FLOWCTL_OPTION: + /* choose to configure flow_control, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION; + enet_initpara.flow_control = para; + break; + case HASHH_OPTION: + /* choose to configure hashtable_high, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHH_OPTION; + enet_initpara.hashtable_high = para; + break; + case HASHL_OPTION: + /* choose to configure hashtable_low, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHL_OPTION; + enet_initpara.hashtable_low = para; + break; + case FILTER_OPTION: + /* choose to configure framesfilter_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FILTER_OPTION; + enet_initpara.framesfilter_mode = para; + break; + case HALFDUPLEX_OPTION: + /* choose to configure halfduplex_param, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION; + enet_initpara.halfduplex_param = para; + break; + case TIMER_OPTION: + /* choose to configure timer_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; + enet_initpara.timer_config = para; + break; + case INTERFRAMEGAP_OPTION: + /* choose to configure interframegap, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION; + enet_initpara.interframegap = para; + break; + default: + break; + } +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters and the less cared + parameters + \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation + \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex + \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex + \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex + \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex + \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII + \param[in] checksum: IP frame checksum offload function, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function + \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function + \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped + \param[in] recept: frame filter function, only one parameter can be selected + which is shown as below, refer to enet_frmrecept_enum + \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled + \arg ENET_RECEIVEALL: all received frame are forwarded to application + \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames + \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) +{ + uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t media_temp = 0U; + uint32_t timeout = 0U; + uint16_t phy_value = 0U; + ErrStatus phy_state= ERROR, enet_state = ERROR; + + /* PHY interface configuration, configure SMI clock and reset PHY chip */ + if(ERROR == enet_phy_config()){ + _ENET_DELAY_(PHY_RESETDELAY); + if(ERROR == enet_phy_config()){ + return enet_state; + } + } + /* initialize ENET peripheral with generally concerned parameters */ + enet_default_init(); + + /* 1st, configure mediamode */ + media_temp = (uint32_t)mediamode; + /* if is PHY auto negotiation */ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + /* wait for PHY_LINKED_STATUS bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_LINKED_STATUS; + timeout++; + }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* enable auto-negotiation */ + phy_value = PHY_AUTONEGOTIATION; + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_AUTONEGO_COMPLETE; + timeout++; + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* read the result of the auto-negotiation */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + /* configure the duplex mode of MAC following the auto-negotiation result */ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + media_temp = ENET_MODE_FULLDUPLEX; + }else{ + media_temp = ENET_MODE_HALFDUPLEX; + } + /* configure the communication speed of MAC following the auto-negotiation result */ + if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){ + media_temp |= ENET_SPEEDMODE_10M; + }else{ + media_temp |= ENET_SPEEDMODE_100M; + } + }else{ + phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); + phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + /* PHY configuration need some time */ + _ENET_DELAY_(PHY_CONFIGDELAY); + } + /* after configuring the PHY, use mediamode to configure registers */ + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value |= media_temp; + ENET_MAC_CFG = reg_value; + + /* 2st, configure checksum */ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~ENET_DMA_CTL_DTCERFD; + reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); + ENET_DMA_CTL = reg_value; + } + + /* 3rd, configure recept */ + ENET_MAC_FRMF |= (uint32_t)recept; + + /* 4th, configure different function options */ + /* configure forward_frame related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + reg_temp = enet_initpara.forward_frame; + + reg_value = ENET_MAC_CFG; + temp = reg_temp; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_TFCD |ENET_MAC_CFG_APCD)); + temp &= (ENET_MAC_CFG_TFCD | ENET_MAC_CFG_APCD); + reg_value |= temp; + ENET_MAC_CFG = reg_value; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value |= (temp >> 2); + ENET_DMA_CTL = reg_value; + } + + /* configure dmabus_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + temp = enet_initpara.dmabus_mode; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ + |ENET_DMA_BCTL_FPBL | ENET_DMA_BCTL_MB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_maxburst related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + temp = enet_initpara.dma_maxburst; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_arbitration related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + temp = enet_initpara.dma_arbitration; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure store_forward_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + temp = enet_initpara.store_forward_mode; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + } + + /* configure dma_function related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + reg_temp = enet_initpara.dma_function; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + temp &= (ENET_DMA_CTL_DAFRF | ENET_DMA_CTL_OSF); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + + reg_value = ENET_DMA_BCTL; + temp = reg_temp; + /* configure ENET_DMA_BCTL register */ + reg_value &= (~ENET_DMA_BCTL_DFM); + temp &= ENET_DMA_BCTL_DFM; + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure vlan_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + reg_temp = enet_initpara.vlan_config; + + reg_value = ENET_MAC_VLT; + /* configure ENET_MAC_VLT register */ + reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); + reg_value |= reg_temp; + ENET_MAC_VLT = reg_value; + } + + /* configure flow_control related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + reg_temp = enet_initpara.flow_control; + + reg_value = ENET_MAC_FCTL; + temp = reg_temp; + /* configure ENET_MAC_FCTL register */ + reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value |= temp; + ENET_MAC_FCTL = reg_value; + + reg_value = ENET_MAC_FCTH; + temp = reg_temp; + /* configure ENET_MAC_FCTH register */ + reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); + reg_value |= (temp >> 8); + ENET_MAC_FCTH = reg_value; + } + + /* configure hashtable_high related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + ENET_MAC_HLH = enet_initpara.hashtable_high; + } + + /* configure hashtable_low related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + ENET_MAC_HLL = enet_initpara.hashtable_low; + } + + /* configure framesfilter_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + reg_temp = enet_initpara.framesfilter_mode; + + reg_value = ENET_MAC_FRMF; + /* configure ENET_MAC_FRMF register */ + reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + reg_value |= reg_temp; + ENET_MAC_FRMF = reg_value; + } + + /* configure halfduplex_param related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + reg_temp = enet_initpara.halfduplex_param; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure timer_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + reg_temp = enet_initpara.timer_config; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure interframegap related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + reg_temp = enet_initpara.interframegap; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~ENET_MAC_CFG_IGBS; + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + enet_state = SUCCESS; + return enet_state; +} + +/*! + \brief reset all core internal registers located in CLK_TX and CLK_RX + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_software_reset(void) +{ + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + uint32_t dma_flag; + + /* reset all core internal registers located in CLK_TX and CLK_RX */ + ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; + + /* wait for reset operation complete */ + do{ + dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); + timeout++; + }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief check receive frame valid and return frame size + \param[in] none + \param[out] none + \retval size of received frame: 0x0 - 0x3FFF +*/ +uint32_t enet_rxframe_size_get(void) +{ + uint32_t size = 0U; + uint32_t status; + + /* get rdes0 information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + + /* if the desciptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + return 0U; + } + + /* if has any error, or the frame uses two or more descriptors */ + if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if(((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FRMT) && + ((uint32_t)RESET) != (dma_current_rxdesc->extended_status & ENET_RDES4_IPPLDERR)){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } +#else + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } +#endif + /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + /* get the size of the received data including CRC */ + size = GET_RDES0_FRML(status); + /* substract the CRC size */ + size = size - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; + } + + /* return packet size */ + return size; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode */ + desc_status = ENET_TDES0_TCHM; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief handle current received frame data to application buffer + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the received frame data + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status); + size = size - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offsetbuffer1_addr) + offset)); + } + + }else{ + /* return ERROR */ + return ERROR; + } + } + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief handle application buffer data to transmit it + \param[in] buffer: pointer to the frame data to be transmitted, + note -- if the input is NULL, user should handle the data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) +{ + uint32_t offset = 0U; + uint32_t dma_tbu_flag, dma_tu_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief configure the transmit IP frame checksum offload calculation and insertion + \param[in] desc: the descriptor pointer which users want to configure + \param[in] checksum: IP frame checksum configuration + only one parameter can be selected which is shown as below + \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled + \arg ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled + \arg ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header + \arg ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated + \param[out] none + \retval ErrStatus: ERROR, SUCCESS +*/ +ErrStatus enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum) +{ + if(NULL != desc){ + desc->status &= ~ENET_TDES0_CM; + desc->status |= checksum; + return SUCCESS; + }else{ + return ERROR; + } +} + +/*! + \brief ENET Tx and Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_enable(void) +{ + enet_tx_enable(); + enet_rx_enable(); +} + +/*! + \brief ENET Tx and Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_disable(void) +{ + enet_tx_disable(); + enet_rx_disable(); +} + +/*! + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: set MAC address 0 filter + \arg ENET_MAC_ADDRESS1: set MAC address 1 filter + \arg ENET_MAC_ADDRESS2: set MAC address 2 filter + \arg ENET_MAC_ADDRESS3: set MAC address 3 filter + \param[in] paddr: the buffer pointer which stores the MAC address + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[out] none + \retval none +*/ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); + REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr); +} + +/*! + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: get MAC address 0 filter + \arg ENET_MAC_ADDRESS1: get MAC address 1 filter + \arg ENET_MAC_ADDRESS2: get MAC address 2 filter + \arg ENET_MAC_ADDRESS3: get MAC address 3 filter + \param[out] paddr: the buffer pointer which is stored the MAC address + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[in] bufsize: refer to the size of the buffer which stores the MAC address + \arg 6 - 255 + \retval ErrStatus: ERROR, SUCCESS +*/ +ErrStatus enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[], uint8_t bufsize) +{ + if(bufsize < 6U){ + return ERROR; + } + paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); + paddr[1] = ENET_GET_MACADDR(mac_addr, 1U); + paddr[2] = ENET_GET_MACADDR(mac_addr, 2U); + paddr[3] = ENET_GET_MACADDR(mac_addr, 3U); + paddr[4] = ENET_GET_MACADDR(mac_addr, 4U); + paddr[5] = ENET_GET_MACADDR(mac_addr, 5U); + return SUCCESS; +} + +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + +/*! + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; +} + +/*! + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; +} + +/*! + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; +} + +/*! + \brief ENET Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE; + ENET_MAC_CFG &= ~ENET_MAC_CFG_REN; +} + +/*! + \brief put registers value into the application buffer + \param[in] type: register type which will be get, refer to enet_registers_type_enum, + only one parameter can be selected which is shown as below + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT + \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL + \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR + \param[in] num: the number of registers that the user want to get + \param[out] preg: the application buffer pointer for storing the register value + \retval none +*/ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) +{ + uint32_t offset = 0U, max = 0U, limit = 0U; + + offset = (uint32_t)type; + max = (uint32_t)type + num; + limit = sizeof(enet_reg_tab)/sizeof(uint16_t); + + /* prevent element in this array is out of range */ + if(max > limit){ + max = limit; + } + + for(; offset < max; offset++){ + /* get value of the corresponding register */ + *preg = REG32((ENET) + enet_reg_tab[offset]); + preg++; + } +} + +/*! + \brief get the enet debug status from the debug register + \param[in] mac_debug: enet debug status, + only one parameter can be selected which is shown as below + \arg ENET_MAC_RECEIVER_NOT_IDLE: MAC receiver is not in idle state + \arg ENET_RX_ASYNCHRONOUS_FIFO_STATE: Rx asynchronous FIFO status + \arg ENET_RXFIFO_WRITING: RxFIFO is doing write operation + \arg ENET_RXFIFO_READ_STATUS: RxFIFO read operation status + \arg ENET_RXFIFO_STATE: RxFIFO state + \arg ENET_MAC_TRANSMITTER_NOT_IDLE: MAC transmitter is not in idle state + \arg ENET_MAC_TRANSMITTER_STATUS: status of MAC transmitter + \arg ENET_PAUSE_CONDITION_STATUS: pause condition status + \arg ENET_TXFIFO_READ_STATUS: TxFIFO read operation status + \arg ENET_TXFIFO_WRITING: TxFIFO is doing write operation + \arg ENET_TXFIFO_NOT_EMPTY: TxFIFO is not empty + \arg ENET_TXFIFO_FULL: TxFIFO is full + \param[out] none + \retval value of the status users want to get +*/ +uint32_t enet_debug_status_get(uint32_t mac_debug) +{ + uint32_t temp_state = 0U; + + switch(mac_debug){ + case ENET_RX_ASYNCHRONOUS_FIFO_STATE: + temp_state = GET_MAC_DBG_RXAFS(ENET_MAC_DBG); + break; + case ENET_RXFIFO_READ_STATUS: + temp_state = GET_MAC_DBG_RXFRS(ENET_MAC_DBG); + break; + case ENET_RXFIFO_STATE: + temp_state = GET_MAC_DBG_RXFS(ENET_MAC_DBG); + break; + case ENET_MAC_TRANSMITTER_STATUS: + temp_state = GET_MAC_DBG_SOMT(ENET_MAC_DBG); + break; + case ENET_TXFIFO_READ_STATUS: + temp_state = GET_MAC_DBG_TXFRS(ENET_MAC_DBG); + break; + default: + if(RESET != (ENET_MAC_DBG & mac_debug)){ + temp_state = 0x1U; + } + break; + } + return temp_state; +} + +/*! + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable + \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_enable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: disable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_disable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter + \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter + \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter + \param[in] addr_mask: select which MAC address bytes will be mask, + one or more parameters can be selected which are shown as below + \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits + \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits + \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits + \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits + \param[in] filter_type: select which MAC address filter type will be selected, + only one parameter can be selected which is shown as below + \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame + \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame + \param[out] none + \retval none +*/ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) +{ + uint32_t reg; + + /* get the address filter register value which is to be configured */ + reg = REG32(ENET_ADDRH_BASE + mac_addr); + + /* clear and configure the address filter register */ + reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF); + reg |= (addr_mask | filter_type); + REG32(ENET_ADDRH_BASE + mac_addr) = reg; +} + +/*! + \brief PHY interface configuration (configure SMI clock and reset PHY chip) + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_config(void) +{ + uint32_t ahbclk; + uint32_t reg; + uint16_t phy_value; + ErrStatus enet_state = ERROR; + + /* clear the previous MDC clock */ + reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + /* get the HCLK frequency */ + ahbclk = rcu_clock_freq_get(CK_AHB); + + /* configure MDC clock according to HCLK frequency range */ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + reg |= ENET_MDC_HCLK_DIV16; + }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + reg |= ENET_MDC_HCLK_DIV26; + }else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)){ + reg |= ENET_MDC_HCLK_DIV42; + }else if((ENET_RANGE(ahbclk, 100000000U, 168000000U))||(168000000U == ahbclk)){ + reg |= ENET_MDC_HCLK_DIV62; + }else{ + return enet_state; + } + ENET_MAC_PHY_CTL = reg; + + /* reset PHY */ + phy_value = PHY_RESET; + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + /* PHY reset need some time */ + _ENET_DELAY_(ENET_DELAY_TO); + + /* check whether PHY reset is complete */ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + + /* PHY reset complete */ + if(RESET == (phy_value & PHY_RESET)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief write to / read from a PHY register + \param[in] direction: only one parameter can be selected which is shown as below + \arg ENET_PHY_WRITE: write data to phy register + \arg ENET_PHY_READ: read data from phy register + \param[in] phy_address: 0x0 - 0x1F + \param[in] phy_reg: 0x0 - 0x1F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue) +{ + uint32_t reg, phy_flag; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* configure ENET_MAC_PHY_CTL with write/read operation */ + reg = ENET_MAC_PHY_CTL; + reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + + /* if do the write operation, write value to the register */ + if(ENET_PHY_WRITE == direction){ + ENET_MAC_PHY_DATA = *pvalue; + } + + /* do PHY write/read operation, and wait the operation complete */ + ENET_MAC_PHY_CTL = reg; + do{ + phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); + timeout++; + } + while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + enet_state = SUCCESS; + } + + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction){ + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + } + + return enet_state; +} + +/*! + \brief enable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_enable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* enable the PHY loopback mode */ + temp_phy |= PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief disable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_disable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* disable the PHY loopback mode */ + temp_phy &= (uint16_t)~PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief enable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_enable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG |= mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP))); + ENET_DMA_CTL |= (mask >> 2); +} + +/*! + \brief disable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_disable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG &= ~mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP))); + ENET_DMA_CTL &= ~(mask >> 2); +} + +/*! + \brief enable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_enable(uint32_t feature) +{ + ENET_MAC_FRMF |= feature; +} + +/*! + \brief disable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_disable(uint32_t feature) +{ + ENET_MAC_FRMF &= ~feature; +} + +/*! + \brief generate the pause frame, ENET will send pause frame after enable transmit flow control + this function only use in full-dulex mode + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state =ERROR; + uint32_t temp = 0U; + + /* in full-duplex mode, must make sure this bit is 0 before writing register */ + temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; + if(RESET == temp){ + ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; + enet_state = SUCCESS; + } + return enet_state; +} + +/*! + \brief configure the pause frame detect type + \param[in] detect: pause frame detect type, + only one parameter can be selected which is shown as below + \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also + use the MAC0 address to detecting pause frame + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + in IEEE802.3 can be detected + \param[out] none + \retval none +*/ +void enet_pauseframe_detect_config(uint32_t detect) +{ + ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT; + ENET_MAC_FCTL |= detect; +} + +/*! + \brief configure the pause frame parameters + \param[in] pausetime: pause time in transmit pause control frame + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, + this value must make sure to be less than configured pause time, only one parameter can be + selected which is shown as below + \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times + \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times + \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times + \arg ENET_PAUSETIME_MINUS256: pause time minus 256 slot times + \param[out] none + \retval none +*/ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) +{ + ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS); + ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold); +} + +/*! + \brief configure the threshold of the flow control(deactive and active threshold) + \param[in] deactive: the threshold of the deactive flow control, this value + should always be less than active flow control value, only one + parameter can be selected which is shown as below + \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[in] active: the threshold of the active flow control, only one parameter + can be selected which is shown as below + \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[out] none + \retval none +*/ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) +{ + ENET_MAC_FCTH = ((deactive | active) >> 8); +} + +/*! + \brief enable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_enable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL |= feature; +} + +/*! + \brief disable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_disable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL &= ~feature; +} + +/*! + \brief get the dma transmit/receive process state + \param[in] direction: choose the direction of dma process which users want to check, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: dma transmit process + \arg ENET_DMA_RX: dma receive process + \param[out] none + \retval state of dma process, the value range shows below: + ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING, + ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING, + ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING, + ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING +*/ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) +{ + uint32_t reval; + reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction); + return reval; +} + +/*! + \brief poll the DMA transmission/reception enable by writing any value to the + ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception + \param[in] direction: choose the direction of DMA process which users want to resume, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA transmit process + \arg ENET_DMA_RX: DMA receive process + \param[out] none + \retval none +*/ +void enet_dmaprocess_resume(enet_dmadirection_enum direction) +{ + if(ENET_DMA_TX == direction){ + ENET_DMA_TPEN = 0U; + }else{ + ENET_DMA_RPEN = 0U; + } +} + +/*! + \brief check and recover the Rx process + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxprocess_check_recovery(void) +{ + uint32_t status; + + /* get DAV information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + status &= ENET_RDES0_DAV; + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with + receive descriptor address pointer updated by RxDMA controller */ + if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && + (ENET_RDES0_DAV == status)){ + dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + } +} + +/*! + \brief flush the ENET transmit FIFO, and wait until the flush operation completes + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_txfifo_flush(void) +{ + uint32_t flush_state; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* set the FTF bit for flushing transmit FIFO */ + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + /* wait until the flush operation completes */ + do{ + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + timeout++; + }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(RESET == flush_state){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + only one parameter can be selected which is shown as below + \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table + \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by + the RxDMA controller + \arg ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller + \arg ENET_TX_DESC_TABLE: the start address of the transmit descriptor table + \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by + the TxDMA controller + \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller + \param[out] none + \retval address value +*/ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) +{ + uint32_t reval = 0U; + + reval = REG32((ENET) +(uint32_t)addr_get); + return reval; +} + +/*! + \brief get the Tx or Rx descriptor information + \param[in] desc: the descriptor pointer which users want to get information + \param[in] info_get: the descriptor information type which is selected, + only one parameter can be selected which is shown as below + \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size + \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size + \arg RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer + \arg TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted + \arg RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame + \arg TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame + \param[out] none + \retval descriptor information, if value is 0xFFFFFFFFU, means the false input parameter +*/ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch(info_get){ + case RXDESC_BUFFER_1_SIZE: + reval = GET_RDES1_RB1S(desc->control_buffer_size); + break; + case RXDESC_BUFFER_2_SIZE: + reval = GET_RDES1_RB2S(desc->control_buffer_size); + break; + case RXDESC_FRAME_LENGTH: + reval = GET_RDES0_FRML(desc->status); + if(reval > 4U){ + reval = reval - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (desc->status & ENET_RDES0_FRMT))){ + reval = reval + 4U; + } + }else{ + reval = 0U; + } + + break; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_COLLISION_COUNT: + reval = GET_TDES0_COCNT(desc->status); + break; + default: + break; + } + return reval; +} + +/*! + \brief get the number of missed frames during receiving + \param[in] none + \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO + \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller + \retval none +*/ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) +{ + uint32_t temp_counter = 0U; + + temp_counter = ENET_DMA_MFBOCNT; + *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); + *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); +} + +/*! + \brief get the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_UFE: underflow error + \arg ENET_TDES0_EXD: excessive deferral + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_ECO: excessive collision + \arg ENET_TDES0_LCO: late collision + \arg ENET_TDES0_NCA: no carrier + \arg ENET_TDES0_LCA: loss of carrier + \arg ENET_TDES0_IPPE: IP payload error + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_JT: jabber timeout + \arg ENET_TDES0_ES: error summary + \arg ENET_TDES0_IPHE: IP header error + \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + + \arg ENET_RDES0_PCERR: payload checksum error + \arg ENET_RDES0_EXSV: extended status valid + \arg ENET_RDES0_CERR: CRC error + \arg ENET_RDES0_DBERR: dribble bit error + \arg ENET_RDES0_RERR: receive error + \arg ENET_RDES0_RWDT: receive watchdog timeout + \arg ENET_RDES0_FRMT: frame type + \arg ENET_RDES0_LCO: late collision + \arg ENET_RDES0_IPHERR: IP frame header error + \arg ENET_RDES0_TSV: timestamp valid + \arg ENET_RDES0_LDES: last descriptor + \arg ENET_RDES0_FDES: first descriptor + \arg ENET_RDES0_VTAG: VLAN tag + \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_LERR: length error + \arg ENET_RDES0_SAFF: SA filter fail + \arg ENET_RDES0_DERR: descriptor error + \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_DAFF: destination address filter fail + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + FlagStatus enet_flag = RESET; + + if((uint32_t)RESET != (desc->status & desc_flag)){ + enet_flag = SET; + } + + return enet_flag; +} + +/*! + \brief set the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to set flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status |= desc_flag; +} + +/*! + \brief clear the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to clear flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status &= ~desc_flag; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will immediately set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct *desc) +{ + desc->control_buffer_size &= ~ENET_RDES1_DINTC; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time + \param[in] desc: the descriptor pointer which users want to configure + \param[in] delay_time: delay a time of 256*delay_time HCLK, this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct *desc, uint32_t delay_time) +{ + desc->control_buffer_size |= ENET_RDES1_DINTC; + ENET_DMA_RSWDC = DMA_RSWDC_WDCFRS(delay_time); +} + +/*! + \brief drop current receive frame + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxframe_drop(void) +{ + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } + + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + } + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc++; + } + } + } +} + +/*! + \brief enable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_enable(uint32_t feature) +{ + ENET_DMA_CTL |= feature; +} + +/*! + \brief disable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_disable(uint32_t feature) +{ + ENET_DMA_CTL &= ~feature; +} + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/*! + \brief get the bit of extended status flag in ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get the extended status flag + \param[in] desc_status: the extended status want to get, + only one parameter can be selected which is shown as below + \arg ENET_RDES4_IPPLDT: IP frame payload type + \arg ENET_RDES4_IPHERR: IP frame header error + \arg ENET_RDES4_IPPLDERR: IP frame payload error + \arg ENET_RDES4_IPCKSB: IP frame checksum bypassed + \arg ENET_RDES4_IPF4: IP frame in version 4 + \arg ENET_RDES4_IPF6: IP frame in version 6 + \arg ENET_RDES4_PTPMT: PTP message type + \arg ENET_RDES4_PTPOEF: PTP on ethernet frame + \arg ENET_RDES4_PTPVF: PTP version format + \param[out] none + \retval value of extended status +*/ +uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_t desc_status) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch (desc_status){ + case ENET_RDES4_IPPLDT: + reval = GET_RDES4_IPPLDT(desc->extended_status); + break; + case ENET_RDES4_PTPMT: + reval = GET_RDES4_PTPMT(desc->extended_status); + break; + default: + if ((uint32_t)RESET != (desc->extended_status & desc_status)){ + reval = 1U; + }else{ + reval = 0U; + } + } + + return reval; +} + +/*! + \brief configure descriptor to work in enhanced mode + \param[in] none + \param[out] none + \retval none +*/ +void enet_desc_select_enhanced_mode(void) +{ + ENET_DMA_BCTL |= ENET_DMA_BCTL_DFM; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in enhanced chain mode with ptp function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + + /* configuration each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in enhanced ring mode with ptp function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + uint32_t timeout = 0U; + uint32_t rdes0_tsv_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)((dma_current_rxdesc->buffer1_addr) + offset)); + } + }else{ + return ERROR; + } + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_RDES0_TSV flag to be set, the timestamp value is taken and + write to the RDES6 and RDES7 */ + do{ + rdes0_tsv_flag = (dma_current_rxdesc->status & ENET_RDES0_TSV); + timeout++; + }while ((RESET == rdes0_tsv_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_RDES0_TSV flag */ + dma_current_rxdesc->status &= ~ENET_RDES0_TSV; + /* get the timestamp value of the received frame */ + timestamp[0] = dma_current_rxdesc->timestamp_low; + timestamp[1] = dma_current_rxdesc->timestamp_high; + } + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* Clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0; + uint32_t dma_tbu_flag, dma_tu_flag; + uint32_t tdes0_ttmss_flag; + uint32_t timeout = 0; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0; offset < length; offset++){ + (*(__IO uint8_t *)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* Clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->timestamp_low; + timestamp[1] = dma_current_txdesc->timestamp_high; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + } + } + + return SUCCESS; +} + +#else + +/*! + \brief configure descriptor to work in normal mode + \param[in] none + \param[out] none + \retval none +*/ +void enet_desc_select_normal_mode(void) +{ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DFM; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if(ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if(ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive ring mode and set buffer1 size */ + desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] timestamp: pointer to the table which stores the timestamp high and low + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); + } + + }else{ + return ERROR; + } + } + /* copy timestamp value from Rx descriptor to application array */ + timestamp[0] = dma_current_rxdesc->buffer1_addr; + timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with RxDMA descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_rxdesc ++; + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0U, timeout = 0U; + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->buffer1_addr; + timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_txdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with TxDMA descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; + } + } + return SUCCESS; +} + +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/*! + \brief wakeup frame filter register pointer reset + \param[in] none + \param[out] none + \retval none +*/ +void enet_wum_filter_register_pointer_reset(void) +{ + ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR; +} + +/*! + \brief set the remote wakeup frame registers + \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) + \param[out] none + \retval none +*/ +void enet_wum_filter_config(uint32_t pdata[]) +{ + uint32_t num = 0U; + + /* configure ENET_MAC_RWFF register */ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + ENET_MAC_RWFF = pdata[num]; + } +} + +/*! + \brief enable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_POWER_DOWN: power down mode + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_enable(uint32_t feature) +{ + ENET_MAC_WUM |= feature; +} + +/*! + \brief disable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_disable(uint32_t feature) +{ + ENET_MAC_WUM &= (~feature); +} + +/*! + \brief reset the MAC statistics counters + \param[in] none + \param[out] none + \retval none +*/ +void enet_msc_counters_reset(void) +{ + /* reset all counters */ + ENET_MSC_CTL |= ENET_MSC_CTL_CTR; +} + +/*! + \brief enable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_enable(uint32_t feature) +{ + ENET_MSC_CTL |= feature; +} + +/*! + \brief disable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_disable(uint32_t feature) +{ + ENET_MSC_CTL &= (~feature); +} + +/*! + \brief configure MAC statistics counters preset mode + \param[in] mode: MSC counters preset mode, refer to enet_msc_preset_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_PRESET_NONE: do not preset MSC counter + \arg ENET_MSC_PRESET_HALF: preset all MSC counters to almost-half(0x7FFF FFF0) value + \arg ENET_MSC_PRESET_FULL: preset all MSC counters to almost-full(0xFFFF FFF0) value + \param[out] none + \retval none +*/ +void enet_msc_counters_preset_config(enet_msc_preset_enum mode) +{ + ENET_MSC_CTL &= ENET_MSC_PRESET_MASK; + ENET_MSC_CTL |= (uint32_t)mode; +} + +/*! + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter + \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter + \arg ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter + \arg ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter + \arg ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter + \arg ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter + \param[out] none + \retval the MSC counter value +*/ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) +{ + uint32_t reval; + + reval = REG32((ENET + (uint32_t)counter)); + + return reval; +} + +/*! + \brief change subsecond to nanosecond + \param[in] subsecond: subsecond value + \param[out] none + \retval the nanosecond value +*/ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) +{ + uint64_t val = subsecond * 1000000000Ull; + val >>= 31; + return (uint32_t)val; +} + +/*! + \brief change nanosecond to subsecond + \param[in] nanosecond: nanosecond value + \param[out] none + \retval the subsecond value +*/ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond) +{ + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return (uint32_t)val; +} + +/*! + \brief enable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \arg ENET_ALL_RX_TIMESTAMP: all received frames are taken snapshot + \arg ENET_NONTYPE_FRAME_SNAPSHOT: take snapshot when received non type frame + \arg ENET_IPV6_FRAME_SNAPSHOT: take snapshot for IPv6 frame + \arg ENET_IPV4_FRAME_SNAPSHOT: take snapshot for IPv4 frame + \arg ENET_PTP_FRAME_USE_MACADDRESS_FILTER: use MAC address1-3 to filter the PTP frame + \param[out] none + \retval none +*/ +void enet_ptp_feature_enable(uint32_t feature) +{ + ENET_PTP_TSCTL |= feature; +} + +/*! + \brief disable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \arg ENET_ALL_RX_TIMESTAMP: all received frames are taken snapshot + \arg ENET_NONTYPE_FRAME_SNAPSHOT: take snapshot when received non type frame + \arg ENET_IPV6_FRAME_SNAPSHOT: take snapshot for IPv6 frame + \arg ENET_IPV4_FRAME_SNAPSHOT: take snapshot for IPv4 frame + \arg ENET_PTP_FRAME_USE_MACADDRESS_FILTER: use MAC address1-3 to filter the PTP frame + \param[out] none + \retval none +*/ +void enet_ptp_feature_disable(uint32_t feature) +{ + ENET_PTP_TSCTL &= ~feature; +} + +/*! + \brief configure the PTP timestamp function + \param[in] func: only one parameter can be selected which is shown as below + \arg ENET_CKNT_ORDINARY: type of ordinary clock node type for timestamp + \arg ENET_CKNT_BOUNDARY: type of boundary clock node type for timestamp + \arg ENET_CKNT_END_TO_END: type of end-to-end transparent clock node type for timestamp + \arg ENET_CKNT_PEER_TO_PEER: type of peer-to-peer transparent clock node type for timestamp + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \arg ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating + \arg ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating + \arg ENET_SUBSECOND_DIGITAL_ROLLOVER: digital rollover mode + \arg ENET_SUBSECOND_BINARY_ROLLOVER: binary rollover mode + \arg ENET_SNOOPING_PTP_VERSION_2: version 2 + \arg ENET_SNOOPING_PTP_VERSION_1: version 1 + \arg ENET_EVENT_TYPE_MESSAGES_SNAPSHOT: only event type messages are taken snapshot + \arg ENET_ALL_TYPE_MESSAGES_SNAPSHOT: all type messages are taken snapshot except announce, + management and signaling message + \arg ENET_MASTER_NODE_MESSAGE_SNAPSHOT: snapshot is only take for master node message + \arg ENET_SLAVE_NODE_MESSAGE_SNAPSHOT: snapshot is only taken for slave node message + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) +{ + uint32_t temp_config = 0U, temp_state = 0U; + uint32_t timeout = 0U; + ErrStatus enet_state = SUCCESS; + + switch(func){ + case ENET_CKNT_ORDINARY: + case ENET_CKNT_BOUNDARY: + case ENET_CKNT_END_TO_END: + case ENET_CKNT_PEER_TO_PEER: + ENET_PTP_TSCTL &= ~ENET_PTP_TSCTL_CKNT; + ENET_PTP_TSCTL |= (uint32_t)func; + break; + case ENET_PTP_ADDEND_UPDATE: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; + } + break; + case ENET_PTP_SYSTIME_UPDATE: + /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ + do{ + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; + } + break; + case ENET_PTP_SYSTIME_INIT: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; + } + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; + } + + return enet_state; +} + +/*! + \brief configure system time subsecond increment value + \param[in] subsecond: the value will be added to the subsecond value of system time, + this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_ptp_subsecond_increment_config(uint32_t subsecond) +{ + ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond); +} + +/*! + \brief adjusting the clock frequency only in fine update mode + \param[in] add: the value will be added to the accumulator register to achieve time synchronization + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_addend_config(uint32_t add) +{ + ENET_PTP_TSADDEND = add; +} + +/*! + \brief initialize or add/subtract to second of the system time + \param[in] sign: timestamp update positive or negative sign, + only one parameter can be selected which is shown as below + \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time + \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time + \param[in] second: initializing or adding/subtracting to second of the system time + \param[in] subsecond: the current subsecond of the system time + with 0.46 ns accuracy if required accuracy is 20 ns + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) +{ + ENET_PTP_TSUH = second; + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); +} + +/*! + \brief configure the expected target time + \param[in] second: the expected target second time + \param[in] nanosecond: the expected target nanosecond time (signed) + \param[out] none + \retval none +*/ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) +{ + ENET_PTP_ETH = second; + ENET_PTP_ETL = nanosecond; +} + +/*! + \brief get the current system time + \param[in] none + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \retval none +*/ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) +{ + uint32_t temp_sec = 0U, temp_subs = 0U; + + /* get the value of sysytem time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; + temp_subs = (uint32_t)ENET_PTP_TSL; + + /* get sysytem time and construct the enet_ptp_systime_struct structure */ + systime_struct->second = temp_sec; + systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); + systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); + systime_struct->sign = GET_PTP_TSL_STS(temp_subs); +} + +/*! + \brief configure the PPS output frequency + \param[in] freq: PPS output frequency, + only one parameter can be selected which is shown as below + \arg ENET_PPSOFC_1HZ: PPS output 1Hz frequency + \arg ENET_PPSOFC_2HZ: PPS output 2Hz frequency + \arg ENET_PPSOFC_4HZ: PPS output 4Hz frequency + \arg ENET_PPSOFC_8HZ: PPS output 8Hz frequency + \arg ENET_PPSOFC_16HZ: PPS output 16Hz frequency + \arg ENET_PPSOFC_32HZ: PPS output 32Hz frequency + \arg ENET_PPSOFC_64HZ: PPS output 64Hz frequency + \arg ENET_PPSOFC_128HZ: PPS output 128Hz frequency + \arg ENET_PPSOFC_256HZ: PPS output 256Hz frequency + \arg ENET_PPSOFC_512HZ: PPS output 512Hz frequency + \arg ENET_PPSOFC_1024HZ: PPS output 1024Hz frequency + \arg ENET_PPSOFC_2048HZ: PPS output 2048Hz frequency + \arg ENET_PPSOFC_4096HZ: PPS output 4096Hz frequency + \arg ENET_PPSOFC_8192HZ: PPS output 8192Hz frequency + \arg ENET_PPSOFC_16384HZ: PPS output 16384Hz frequency + \arg ENET_PPSOFC_32768HZ: PPS output 32768Hz frequency + \param[out] none + \retval none +*/ +void enet_ptp_pps_output_frequency_config(uint32_t freq) +{ + ENET_PTP_PPSCTL = freq; +} + +/*! + \brief configure and start PTP timestamp counter + \param[in] updatemethod: method for updating + \arg ENET_PTP_FINEMODE: fine correction method + \arg ENET_PTP_COARSEMODE: coarse correction method + \param[in] init_sec: second value for initializing system time + \param[in] init_subsec: subsecond value for initializing system time + \param[in] carry_cfg: the value to be added to the accumulator register (in fine method is used) + \param[in] accuracy_cfg: the value to be added to the subsecond value of system time + \param[out] none + \retval none +*/ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg) +{ + /* mask the timestamp trigger interrupt */ + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + + /* enable timestamp */ + enet_ptp_feature_enable(ENET_ALL_RX_TIMESTAMP | ENET_RXTX_TIMESTAMP); + + /* configure system time subsecond increment based on the PTP clock frequency */ + enet_ptp_subsecond_increment_config(accuracy_cfg); + + if(ENET_PTP_FINEMODE == updatemethod){ + /* fine correction method: configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + /* wait until update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + } + } + + /* choose the fine correction method */ + enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + enet_desc_select_enhanced_mode(); +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ +} + +/*! + \brief adjust frequency in fine method by configure addend register + \param[in] carry_cfg: the value to be added to the accumulator register + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) +{ + /* re-configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config((uint32_t)carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief update system time in coarse method + \param[in] systime_struct: : pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct) +{ + uint32_t subsecond_val; + uint32_t carry_cfg; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* save the carry_cfg value */ + carry_cfg = ENET_PTP_TSADDEND_TMSA; + + /* update the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + + /* wait until the update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + } + + /* write back the carry_cfg value, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief set system time in fine method + \param[in] systime_struct: : pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +{ + uint32_t subsecond_val; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + + /* wait until the system time initialzation finished */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + } +} + +/*! + \brief get the ptp flag status + \param[in] flag: ptp flag status to be checked + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_ptp_flag_get(uint32_t flag) +{ + FlagStatus bitstatus = RESET; + + if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + bitstatus = SET; + } + + return bitstatus; +} + +/*! + \brief reset the ENET initpara struct, call it before using enet_initpara_config() + \param[in] none + \param[out] none + \retval none +*/ +void enet_initpara_reset(void) +{ + enet_initpara.option_enable = 0U; + enet_initpara.forward_frame = 0U; + enet_initpara.dmabus_mode = 0U; + enet_initpara.dma_maxburst = 0U; + enet_initpara.dma_arbitration = 0U; + enet_initpara.store_forward_mode = 0U; + enet_initpara.dma_function = 0U; + enet_initpara.vlan_config = 0U; + enet_initpara.flow_control = 0U; + enet_initpara.hashtable_high = 0U; + enet_initpara.hashtable_low = 0U; + enet_initpara.framesfilter_mode = 0U; + enet_initpara.halfduplex_param = 0U; + enet_initpara.timer_config = 0U; + enet_initpara.interframegap = 0U; +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \param[in] none + \param[out] none + \retval none +*/ +static void enet_default_init(void) +{ + uint32_t reg_value = 0U; + + /* MAC */ + /* configure ENET_MAC_CFG register */ + reg_value = ENET_MAC_CFG; + reg_value &= MAC_CFG_MASK; + reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ + | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_TYPEFRAME_CRC_DROP_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; + ENET_MAC_CFG = reg_value; + + /* configure ENET_MAC_FRMF register */ + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ + |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ + |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ + |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + + /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ + ENET_MAC_HLH = 0x0U; + + ENET_MAC_HLL = 0x0U; + + /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ + reg_value = ENET_MAC_FCTL; + reg_value &= MAC_FCTL_MASK; + reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ + |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ + |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + + /* configure ENET_MAC_VLT register */ + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); + + /* DMA */ + /* configure ENET_DMA_CTL register */ + reg_value = ENET_DMA_CTL; + reg_value &= DMA_CTL_MASK; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ + |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ + |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; + + /* configure ENET_DMA_BCTL register */ + reg_value = ENET_DMA_BCTL; + reg_value &= DMA_BCTL_MASK; + reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ + |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ + |ENET_FIXED_BURST_ENABLE |ENET_MIXED_BURST_DISABLE \ + |ENET_NORMAL_DESCRIPTOR; + ENET_DMA_BCTL = reg_value; +} + +#ifndef USE_DELAY +/*! + \brief insert a delay time + \param[in] ncount: specifies the delay time length + \param[out] none + \param[out] none +*/ +static void enet_delay(uint32_t ncount) +{ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--){ + } +} +#endif /* USE_DELAY */ + +#endif /* GD32F30X_CL */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c new file mode 100644 index 0000000000..8b0fb49e52 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c @@ -0,0 +1,677 @@ +/*! + \file gd32f30x_exmc.c + \brief EXMC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_exmc.h" + +/* EXMC bank0 register reset value */ +#define BANK0_SNCTL_REGION0_RESET ((uint32_t)0x000030DBU) +#define BANK0_SNCTL_REGION1_2_3_RESET ((uint32_t)0x000030D2U) +#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) + +/* EXMC bank1/2 register reset mask */ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000042U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC bank3 register reset mask */ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000043U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC register bit offset */ +#define SNCTL_NRMUX_OFFSET ((uint32_t)1U) +#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U) +#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U) +#define SNCTL_WREN_OFFSET ((uint32_t)12U) +#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U) +#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U) +#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U) + +#define SNTCFG_AHLD_OFFSET ((uint32_t)4U) +#define SNTCFG_DSET_OFFSET ((uint32_t)8U) +#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U) + +#define SNWTCFG_WAHLD_OFFSET ((uint32_t)4U) +#define SNWTCFG_WDSET_OFFSET ((uint32_t)8U) +#define SNWTCFG_WBUSLAT_OFFSET ((uint32_t)16U) + +#define NPCTL_NDWTEN_OFFSET ((uint32_t)1U) +#define NPCTL_ECCEN_OFFSET ((uint32_t)6U) + +#define NPCTCFG_COMWAIT_OFFSET ((uint32_t)8U) +#define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) +#define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) + +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) + +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) + +#define INTEN_INTS_OFFSET ((uint32_t)3U) + +/*! + \brief deinitialize EXMC NOR/SRAM region + \param[in] exmc_norsram_region: select the region of bank0 + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_deinit(uint32_t exmc_norsram_region) +{ + /* reset the registers */ + if(EXMC_BANK0_NORSRAM_REGION0 == exmc_norsram_region){ + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION0_RESET; + }else{ + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION1_2_3_RESET; + } + EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET; + EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET; +} + +/*! + \brief initialize exmc_norsram_parameter_struct with the default values + \param[in] none + \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + /* configure the structure with default values */ + exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; + exmc_norsram_init_struct->address_data_mux = ENABLE; + exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; + exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B; + exmc_norsram_init_struct->burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW; + exmc_norsram_init_struct->wrap_burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE; + exmc_norsram_init_struct->memory_write = ENABLE; + exmc_norsram_init_struct->nwait_signal = ENABLE; + exmc_norsram_init_struct->extended_mode = DISABLE; + exmc_norsram_init_struct->asyn_wait = DISABLE; + exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; + + /* read/write timing configure */ + exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK; + exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; + exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; + + /* write timing configure, when extended mode is used */ + exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; +} + +/*! + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 + write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + write_timing: struct exmc_norsram_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + uint32_t snctl = 0x00000000U,sntcfg = 0x00000000U,snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | + EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | + EXMC_SNCTL_SYNCWR )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )| + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )| + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; + } + + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) | + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )| + (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )| + (((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) | + exmc_norsram_init_struct->write_timing->asyn_access_mode; + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } + + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; +} + +/*! + \brief enable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_enable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief disable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM Bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_disable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief deinitialize EXMC NAND bank + \param[in] exmc_nand_bank: select the bank of NAND + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1..2) + \param[out] none + \retval none +*/ +void exmc_nand_deinit(uint32_t exmc_nand_bank) +{ + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET; + EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET; + EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET; + EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET; +} + +/*! + \brief initialize exmc_norsram_parameter_struct with the default values + \param[in] none + \param[out] the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default values */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief initialize EXMC NAND bank + \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter + nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND + ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + ecc_logic: ENABLE or DISABLE + databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; + EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; + EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; +} + +/*! + \brief enable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_enable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_disable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_NDBKEN); +} + +/*! + \brief deinitialize EXMC PC card bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_deinit(void) +{ + /* EXMC_BANK3_PCCARD */ + EXMC_NPCTL3 = BANK3_NPCTL_RESET; + EXMC_NPINTEN3 = BANK3_NPINTEN_RESET; + EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET; + EXMC_NPATCFG3 = BANK3_NPATCFG_RESET; + EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; +} + +/*! + \brief initialize exmc_pccard_parameter_struct parameter with the default values + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the structure with default values */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )| + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )| + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + +/*! + \brief enable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_enable(void) +{ + EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_disable(void) +{ + EXMC_NPCTL3 &= (~EXMC_NPCTL_NDBKEN); +} + +/*! + \brief configure CRAM page size + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[in] page_size: CRAM page size + only one parameter can be selected which is shown as below: + \arg EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access + \arg EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes + \arg EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes + \arg EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes + \arg EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes + \param[out] none + \retval none +*/ +void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size) +{ + /* reset the bits */ + EXMC_SNCTL(exmc_norsram_region) &= ~EXMC_SNCTL_CPS; + + /* set the CPS bits */ + EXMC_SNCTL(exmc_norsram_region) |= page_size; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_ECCEN); + } +} + +/*! + \brief get the EXMC ECC value + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank) +{ + return (EXMC_NECC(exmc_nand_bank)); +} + +/*! + \brief enable EXMC interrupt + \param[in] exmc_bank: specifies the NAND bank,PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) |= interrupt; +} + +/*! + \brief disable EXMC interrupt + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= (~interrupt); +} + +/*! + \brief get EXMC flag status + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC Card bank + \param[in] flag: EXMC status and flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag) +{ + uint32_t status = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(exmc_bank); + + if ((status & flag) != (uint32_t)flag ){ + /* flag is reset */ + return RESET; + }else{ + /* flag is set */ + return SET; + } +} + +/*! + \brief clear EXMC flag status + \param[in] exmc_bank: specifie the NAND bank , PCCARD bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] flag: EXMC status and flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval none +*/ +void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= (~flag); +} + +/*! + \brief get EXMC interrupt flag + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt) +{ + uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(exmc_bank); + interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET)); + + interrupt_enable = (status & interrupt); + + if ((interrupt_enable) && (interrupt_state)){ + /* interrupt flag is set */ + return SET; + }else{ + /* interrupt flag is reset */ + return RESET; + } +} + +/*! + \brief clear EXMC interrupt flag + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= ~(interrupt >> INTEN_INTS_OFFSET); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c new file mode 100644 index 0000000000..4708a15627 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c @@ -0,0 +1,253 @@ +/*! + \file gd32f30x_exti.c + \brief EXTI driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_exti.h" + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none +*/ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = (uint32_t)0x00000000U; + EXTI_EVEN = (uint32_t)0x00000000U; + EXTI_RTEN = (uint32_t)0x00000000U; + EXTI_FTEN = (uint32_t)0x00000000U; + EXTI_SWIEV = (uint32_t)0x00000000U; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling trigger + \arg EXTI_TRIG_BOTH: rising and falling trigger + \param[out] none + \retval none +*/ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN &= ~(uint32_t)linex; + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch(mode){ + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t)linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t)linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch(trig_type){ + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t)linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t)linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t)linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t)linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t)linex; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c new file mode 100644 index 0000000000..d3b1a12256 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c @@ -0,0 +1,1009 @@ +/*! + \file gd32f30x_fmc.c + \brief FMC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "gd32f30x_fmc.h" + +/*! + \brief set the wait state counter value + \param[in] wscnt:wait state counter value + \arg WS_WSCNT_0: FMC 0 wait + \arg WS_WSCNT_1: FMC 1 wait + \arg WS_WSCNT_2: FMC 2 wait + \param[out] none + \retval none +*/ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* write the FMC unlock key */ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } + } +} + +/*! + \brief unlock the FMC bank0 operation + this function can be used for all GD32F30x devices. + for GD32F30x with flash more than 512KB, this function unlocks bank0. + for GD32F30x with flash no more than 512KB and it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } +} + +/*! + \brief unlock the FMC bank1 operation + this function can be used for GD32F30x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_unlock(void) +{ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + /* write the FMC unlock key */ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL0 |= FMC_CTL0_LK; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* set the LK bit */ + FMC_CTL1 |= FMC_CTL1_LK; + } +} + +/*! + \brief lock the FMC bank0 operation + this function can be used for all GD32F30X devices. + for GD32F30x with flash more than 512KB, this function locks bank0. + for GD32F30x with flash no more than 512KB and it is equivalent to fmc_lock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_lock(void) +{ + /* set the LK bit*/ + FMC_CTL0 |= FMC_CTL0_LK; +} + +/*! + \brief lock the FMC bank1 operation + this function can be used for GD32F30x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_lock(void) +{ + /* set the LK bit*/ + FMC_CTL1 |= FMC_CTL1_LK; +} + +/*! + \brief erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > page_address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + }else{ + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL1 |= FMC_CTL1_PER; + FMC_ADDR1 = page_address; + if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + FMC_ADDR0 = page_address; + } + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL1 &= ~FMC_CTL1_PER; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY != fmc_state){ + return fmc_state; + } + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase bank0 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank0 erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief erase bank1 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank1 erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address without erasing + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval fmc_state +*/ +fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + FMC_WSEN |= FMC_WSEN_BPEN; + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + FMC_WSEN |= FMC_WSEN_BPEN; + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + FMC_WSEN |= FMC_WSEN_BPEN; + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL0 &= ~FMC_CTL0_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL0 and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + /* no security protection */ + OB_SPC = (uint16_t)temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected + \arg OB_WPx(x=0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t)(~ob_wp); + temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + + /* start the option byte program */ + FMC_CTL0 |= FMC_CTL0_OBPG; + + OB_SPC = (uint16_t)ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t)temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program option bytes data + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC user option byte + \param[in] none + \param[out] none + \retval the FMC user option byte values +*/ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t)(FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data +*/ +uint16_t ob_data_get(void) +{ + return (uint16_t)(FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value +*/ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get the FMC option byte security protection + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt + \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt + \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt + \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt + \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit + \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval none +*/ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + FlagStatus ret1 = RESET; + FlagStatus ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); + }else{ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval none +*/ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC bank0 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC bank1 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ + fmc_state = FMC_PGERR; + } + } + } + + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank0 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank0_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank1 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank1_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c new file mode 100644 index 0000000000..9a5014ae43 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c @@ -0,0 +1,158 @@ +/*! + \file gd32f30x_fwdgt.c + \brief FWDGT driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + FWDGT_RLD = RLD_RLD(reload_value); + + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(RESET != (FWDGT_STAT & flag)){ + return SET; + } + + return RESET; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c new file mode 100644 index 0000000000..dd0ff97eeb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c @@ -0,0 +1,583 @@ +/*! + \file gd32f30x_gpio.c + \brief GPIO driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch(gpio_periph){ + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + case GPIOF: + /* reset GPIOF */ + rcu_periph_reset_enable(RCU_GPIOFRST); + rcu_periph_reset_disable(RCU_GPIOFRST); + break; + case GPIOG: + /* reset GPIOG */ + rcu_periph_reset_enable(RCU_GPIOGRST); + rcu_periph_reset_disable(RCU_GPIOGRST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \arg GPIO_OSPEED_MAX: output max speed more than 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); + + /* GPIO speed configuration */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ + /* output mode max speed */ + if(GPIO_OSPEED_MAX == (uint32_t)speed){ + temp_mode |= (uint32_t)0x03U; + /* set the corresponding SPD bit */ + GPIOx_SPD(gpio_periph) |= (uint32_t)pin ; + }else{ + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t)speed; + } + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for(i = 0U;i < 8U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for(i = 8U;i < 16U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) +{ + if(RESET != bit_value){ + GPIO_BOP(gpio_periph) = (uint32_t)pin; + }else{ + GPIO_BC(gpio_periph) = (uint32_t)pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph,uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t)data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t)(GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t)GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + only one parameter can be selected which are shown as below: + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN_PARTIAL_REMAP: CAN partial remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_CAN_FULL_REMAP: CAN full remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(only for GD32F30X_CL devices) + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping(only for GD32F30X_CL devices) + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping + \arg GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ENET_REMAP: ENET remapping(only for GD32F30X_CL devices) + \arg GPIO_CAN1_REMAP: CAN1 remapping(only for GD32F30X_CL devices) + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping + \arg GPIO_TIMER1ITR0_REMAP: TIMER1 internal trigger 0 remapping(only for GD32F30X_CL devices) + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32F30X_CL devices) + \arg GPIO_TIMER8_REMAP: TIMER8 remapping + \arg GPIO_TIMER9_REMAP: TIMER9 remapping + \arg GPIO_TIMER10_REMAP: TIMER10 remapping + \arg GPIO_TIMER12_REMAP: TIMER12 remapping + \arg GPIO_TIMER13_REMAP: TIMER13 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \arg GPIO_CTC_REMAP0: CTC remapping(PD15) + \arg GPIO_CTC_REMAP1: CTC remapping(PF0) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if(((uint32_t)0x80000000U) == (remap & 0x80000000U)){ + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + }else{ + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + }else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){ + remap2 = ((uint32_t)0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + }else{ + temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if(DISABLE != newvalue){ + temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U)); + } + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){ + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + }else{ + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +#ifdef GD32F30X_CL +/*! + \brief select ethernet MII or RMII PHY + \param[in] enet_sel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t enet_sel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)enet_sel; +} +#endif /* GD32F30X_CL */ + +/*! + \brief select GPIO pin exti sources + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOF: output port source F + \arg GPIO_PORT_SOURCE_GPIOG: output port source G + \param[in] output_pin: GPIO output pin source + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if(GPIO_PIN_SOURCE_4 > output_pin){ + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_8 > output_pin){ + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_12 > output_pin){ + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else{ + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \param[in] output_pin: GPIO event output pin + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); + + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t)output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + GPIO_LOCK(gpio_periph) = (uint32_t)pin; + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} + +/*! + \brief configure the I/O compensation cell + \param[in] compensation: specifies the I/O compensation cell mode + only one parameter can be selected which are shown as below: + \arg GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled + \arg GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled + \param[out] none + \retval none +*/ +void gpio_compensation_config(uint32_t compensation) +{ + uint32_t reg; + reg = AFIO_CPSCTL; + + /* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */ + reg &= ~AFIO_CPSCTL_CPS_EN; + AFIO_CPSCTL = (reg | compensation); +} + +/*! + \brief check the I/O compensation cell is ready or not + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus gpio_compensation_flag_get(void) +{ + if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){ + return SET; + }else{ + return RESET; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c new file mode 100644 index 0000000000..2da8dac538 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c @@ -0,0 +1,737 @@ +/*! + \file gd32f30x_i2c.c + \brief I2C driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-04-16, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_i2c.h" + +#define I2C_ERROR_HANDLE(s) do{}while(1) + +#define I2CCLK_MAX ((uint32_t)0x0000003CU) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_deinit(uint32_t i2c_periph) +{ + switch(i2c_periph){ + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none +*/ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) +{ + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; + + /* check the clkspeed value */ + if(0U == clkspeed){ + I2C_ERROR_HANDLE("the parameter can not be 0 \r\n"); + } + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if(100000U >= clkspeed){ + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t)((pclk1/1000000U)+1U); + if(risetime >= I2CCLK_MAX){ + I2C_RT(i2c_periph) = I2CCLK_MAX; + }else if(risetime <= I2CCLK_MIN){ + I2C_RT(i2c_periph) = I2CCLK_MIN; + }else{ + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t)(pclk1/(clkspeed*2U)); + if(clkc < 0x04U){ + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + }else{ + /* fast mode plus, the maximum SCL rise time is 120ns */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)120U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + /* enable fast mode */ + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + /* enable I2C fast mode plus */ + I2C_FMPCFG(i2c_periph) = I2C_FMPCFG_FMPEN; + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none +*/ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none +*/ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if(I2C_SMBUS_HOST == type){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none +*/ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none +*/ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dualaddr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr) +{ + /* configure address */ + dualaddr = dualaddr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | dualaddr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received +*/ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none +*/ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none +*/ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none +*/ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none +*/ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none +*/ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none +*/ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none +*/ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value +*/ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>>STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none +*/ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none +*/ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none +*/ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] intflag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c new file mode 100644 index 0000000000..884d312355 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c @@ -0,0 +1,175 @@ +/*! + \file gd32f30x_misc.c + \brief MISC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_misc.h" + +/*! + \brief set the priority group + \param[in] nvic_prigroup: the NVIC priority group + \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \param[out] none + \retval none +*/ +void nvic_priority_group_set(uint32_t nvic_prigroup) +{ + /* set the priority group value */ + SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; +} + +/*! + \brief enable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set + \param[in] nvic_irq_sub_priority: the subpriority needed to set + \param[out] none + \retval none +*/ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, + uint8_t nvic_irq_sub_priority) +{ + uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; + /* use the priority group value to get the temp_pre and the temp_sub */ + if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE0_SUB4){ + temp_pre=0U; + temp_sub=0x4U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE1_SUB3){ + temp_pre=1U; + temp_sub=0x3U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE2_SUB2){ + temp_pre=2U; + temp_sub=0x2U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE3_SUB1){ + temp_pre=3U; + temp_sub=0x1U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE4_SUB0){ + temp_pre=4U; + temp_sub=0x0U; + }else{ + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre=2U; + temp_sub=0x2U; + } + /* get the temp_priority to fill the NVIC->IP register */ + temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); + temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority = temp_priority << 0x04U; + NVIC->IP[nvic_irq] = (uint8_t)temp_priority; + /* enable the selected IRQ */ + NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief disable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void nvic_irq_disable(uint8_t nvic_irq) +{ + /* disable the selected IRQ.*/ + NVIC->ICER[nvic_irq >> 0x05] = (uint32_t)0x01 << (nvic_irq & (uint8_t)0x1F); +} + +/*! + \brief set the NVIC vector table base address + \param[in] nvic_vict_tab: the RAM or FLASH base address + \arg NVIC_VECTTAB_RAM: RAM base address + \are NVIC_VECTTAB_FLASH: Flash base address + \param[in] offset: Vector Table offset + \param[out] none + \retval none +*/ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) +{ + SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); +} + +/*! + \brief set the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + by all the enable and disable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_set(uint8_t lowpower_mode) +{ + SCB->SCR |= (uint32_t)lowpower_mode; +} + +/*! + \brief reset the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + woke up by the enable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_reset(uint8_t lowpower_mode) +{ + SCB->SCR &= (~(uint32_t)lowpower_mode); +} + +/*! + \brief set the systick clock source + \param[in] systick_clksource: the systick clock source needed to choose + \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK + \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 + \param[out] none + \retval none +*/ + +void systick_clksource_set(uint32_t systick_clksource) +{ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + /* set the systick clock source from HCLK */ + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + }else{ + /* set the systick clock source from HCLK/8 */ + SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c new file mode 100644 index 0000000000..164274c0eb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c @@ -0,0 +1,386 @@ +/*! + \file gd32f30x_pmu.c + \brief PMU driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "gd32f30x_pmu.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + \arg PMU_LVDT_0: voltage threshold is 2.1V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.6V + \arg PMU_LVDT_4: voltage threshold is 2.7V + \arg PMU_LVDT_5: voltage threshold is 2.9V + \arg PMU_LVDT_6: voltage threshold is 3.0V + \arg PMU_LVDT_7: voltage threshold is 3.1V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief select LDO output voltage + this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL + \param[in] ldo_output: + \arg PMU_LDOVS_LOW: LDO output voltage low mode + \arg PMU_LDOVS_MID: LDO output voltage mid mode + \arg PMU_LDOVS_HIGH: LDO output voltage high mode + \param[out] none + \retval none +*/ +void pmu_ldo_output_select(uint32_t ldo_output) +{ + PMU_CTL &= ~PMU_CTL_LDOVS; + PMU_CTL |= ldo_output; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief switch high-driver mode + this bit set by software only when IRC16M or HXTAL used as system clock + \param[in] highdr_switch: + \arg PMU_HIGHDR_SWITCH_NONE: disable high-driver mode switch + \arg PMU_HIGHDR_SWITCH_EN: enable high-driver mode switch + \param[out] none + \retval none +*/ +void pmu_highdriver_switch_select(uint32_t highdr_switch) +{ + /* wait for HDRF flag set */ + while(SET != pmu_flag_get(PMU_FLAG_HDRF)){ + } + PMU_CTL &= ~PMU_CTL_HDS; + PMU_CTL |= highdr_switch; +} + +/*! + \brief enable high-driver mode + this bit set by software only when IRC16M or HXTAL used as system clock + \param[in] none + \param[out] none + \retval none +*/ +void pmu_highdriver_mode_enable(void) +{ + PMU_CTL |= PMU_CTL_HDEN; +} + +/*! + \brief disable high-driver mode + \param[in] none + \param[out] none + \retval none +*/ +void pmu_highdriver_mode_disable(void) +{ + PMU_CTL &= ~PMU_CTL_HDEN; +} + +/*! + \brief enable low-driver mode in deep-sleep mode + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lowdriver_mode_enable(void) +{ + PMU_CTL |= PMU_CTL_LDEN; +} + +/*! + \brief disable low-driver mode in deep-sleep mode + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lowdriver_mode_disable(void) +{ + PMU_CTL &= ~PMU_CTL_LDEN; +} + +/*! + \brief driver mode when use low power LDO + \param[in] mode: + \arg PMU_NORMALDR_LOWPWR: normal driver when use low power LDO + \arg PMU_LOWDR_LOWPWR: low-driver mode enabled when LDEN is 11 and use low power LDO + \param[out] none + \retval none +*/ +void pmu_lowpower_driver_config(uint32_t mode) +{ + PMU_CTL &= ~PMU_CTL_LDLP; + PMU_CTL |= mode; +} + +/*! + \brief driver mode when use normal power LDO + \param[in] mode: + \arg PMU_NORMALDR_NORMALPWR: normal driver when use normal power LDO + \arg PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and use normal power LDO + \param[out] none + \retval none +*/ +void pmu_normalpower_driver_config(uint32_t mode) +{ + PMU_CTL &= ~PMU_CTL_LDNP; + PMU_CTL |= mode; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo + \arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + static uint32_t reg_snap[ 4 ]; + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + + /* set sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + reg_snap[ 0 ] = REG32( 0xE000E010U ); + reg_snap[ 1 ] = REG32( 0xE000E100U ); + reg_snap[ 2 ] = REG32( 0xE000E104U ); + reg_snap[ 3 ] = REG32( 0xE000E108U ); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF83DU; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFFFFFU; + + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + __SEV(); + __WFE(); + __WFE(); + } + + REG32( 0xE000E010U ) = reg_snap[ 0 ] ; + REG32( 0xE000E100U ) = reg_snap[ 1 ] ; + REG32( 0xE000E104U ) = reg_snap[ 2 ] ; + REG32( 0xE000E108U ) = reg_snap[ 3 ] ; + + /* reset sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief enable backup domain write + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable backup domain write + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} + +/*! + \brief get flag state + \param[in] flag: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \arg PMU_FLAG_LDOVSRF: LDO voltage select ready flag + \arg PMU_FLAG_HDRF: high-driver ready flag + \arg PMU_FLAG_HDSRF: high-driver switch ready flag + \arg PMU_FLAG_LDRF: low-driver mode ready flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c new file mode 100644 index 0000000000..f731d22c58 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c @@ -0,0 +1,1326 @@ +/*! + \file gd32f30x_rcu.c + \brief RCU driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) /* IRC8M is selected as CK_SYS */ +#define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */ +#define SEL_PLL ((uint16_t)2U) /* PLL is selected as CK_SYS */ + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU) + +/* ADC clock prescaler offset */ +#define RCU_ADC_PSC_OFFSET ((uint32_t)14U) + +/* RCU IRC8M adjust value mask and offset*/ +#define RCU_IRC8M_ADJUST_MASK ((uint8_t)0x1FU) +#define RCU_IRC8M_ADJUST_OFFSET ((uint32_t)3U) + +/* RCU PLL1 clock multiplication factor offset */ +#define RCU_CFG1_PLL1MF_OFFSET ((uint32_t)8U) +/* RCU PREDV1 division factor offset*/ +#define RCU_CFG1_PREDV1_OFFSET ((uint32_t)4U) + + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset CFG0 register */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | + RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); +#elif defined(GD32F30X_CL) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBFSPSC_2); +#endif /* GD32F30X_HD and GD32F30X_XD */ + /* reset CTL register */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + RCU_CTL &= ~RCU_CTL_HXTALBPS; +#ifdef GD32F30X_CL + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); +#endif /* GD32F30X_CL */ + + /* reset INT and CFG1 register */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_INT = 0x009f0000U; + RCU_CFG1 &= ~(RCU_CFG1_ADCPSC_3 | RCU_CFG1_PLLPRESEL); +#elif defined(GD32F30X_CL) + RCU_INT = 0x00ff0000U; + RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | + RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_ADCPSC_3 | + RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); +#endif /* GD32F30X_HD and GD32F30X_XD */ +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_CTC: CTC clock + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF: alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_CTC: CTC clock + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC + \arg RCU_CTCRST: reset CTC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC + \arg RCU_CTCRST: reset CTC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL selected + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the CKOUT0SRC, set according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL_MULx (XD series x = 2..63, CL series x = 2..14, 16..63, 6.5) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +/*! + \brief configure the PLL clock source preselection + \param[in] pll_presel: PLL clock source preselection + only one parameter can be selected which is shown as below: + \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PLL source clock + \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock + \param[out] none + \retval none +*/ +void rcu_pllpresel_config(uint32_t pll_presel) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + + /* PLL clock source preselection */ + reg &= ~RCU_CFG1_PLLPRESEL; + reg |= pll_presel; + + RCU_CFG1 = reg; +} + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +/*! + \brief configure the PREDV0 division factor + \param[in] predv0_div: PREDV0 division factor + \arg RCU_PREDV0_DIVx, x = 1,2 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + /* reset PREDV0 bit */ + reg &= ~RCU_CFG0_PREDV0; + if(RCU_PREDV0_DIV2 == predv0_div){ + /* set the PREDV0 bit */ + reg |= RCU_CFG0_PREDV0; + } + + RCU_CFG0 = reg; +} +#elif defined(GD32F30X_CL) +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..14,16,20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..14,16,20,18..32,40) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB/5 + \arg RCU_CKADC_CKAHB_DIV6: ADC prescaler select CK_AHB/6 + \arg RCU_CKADC_CKAHB_DIV10: ADC prescaler select CK_AHB/10 + \arg RCU_CKADC_CKAHB_DIV20: ADC prescaler select CK_AHB/20 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0,reg1; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + reg1 = RCU_CFG1; + reg1 &= ~RCU_CFG1_ADCPSC_3; + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= ((adc_psc << RCU_ADC_PSC_OFFSET) | RCU_CFG0_ADCPSC_2); + break; + + case RCU_CKADC_CKAHB_DIV5: + case RCU_CKADC_CKAHB_DIV6: + case RCU_CKADC_CKAHB_DIV10: + case RCU_CKADC_CKAHB_DIV20: + adc_psc &= ~BITS(2,3); + reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); + reg1 |= RCU_CFG1_ADCPSC_3; + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; + RCU_CFG1 = reg1; +} + +/*! + \brief configure the USBD/USBFS prescaler factor + \param[in] usb_psc: USB prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKUSB_CKPLL_DIV1_5: USBD/USBFS prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBD/USBFS prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBD/USBFS prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBD/USBFS prescaler select CK_PLL/2 + \arg RCU_CKUSB_CKPLL_DIV3: USBD/USBFS prescaler select CK_PLL/3 + \arg RCU_CKUSB_CKPLL_DIV3_5: USBD/USBFS prescaler select CK_PLL/3.5 + \arg RCU_CKUSB_CKPLL_DIV4: USBD/USBFS prescaler select CK_PLL/4 + \param[out] none + \retval none +*/ +void rcu_usb_clock_config(uint32_t usb_psc) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* configure the USBD/USBFS prescaler factor */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + reg &= ~RCU_CFG0_USBDPSC; +#elif defined(GD32F30X_CL) + reg &= ~RCU_CFG0_USBFSPSC; +#endif /* GD32F30X_HD and GD32F30X_XD */ + + RCU_CFG0 = (reg | usb_psc); +} + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +#ifdef GD32F30X_CL +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} +#endif /* GD32F30X_CL */ + +/*! + \brief configure the CK48M clock source selection + \param[in] ck48m_clock_source: CK48M clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock + \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock + \param[out] none + \retval none +*/ +void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) +{ + uint32_t reg; + + reg = RCU_ADDCTL; + /* reset the CK48MSEL bit and set according to ck48m_clock_source */ + reg &= ~RCU_ADDCTL_CK48MSEL; + RCU_ADDCTL = (reg | ck48m_clock_source); +} + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only) + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only) + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval none +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization interrupt and ckm flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag) +{ + RCU_REG_VAL(int_flag) |= BIT(RCU_BIT_POS(int_flag)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum interrupt) +{ + RCU_REG_VAL(interrupt) |= BIT(RCU_BIT_POS(interrupt)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum interrupt) +{ + RCU_REG_VAL(interrupt) &= ~BIT(RCU_BIT_POS(interrupt)); +} + +/*! + \brief configure the LXTAL drive capability + \param[in] lxtal_dricap: drive capability of LXTAL + only one parameter can be selected which is shown as below: + \arg RCU_LXTAL_LOWDRI: lower driving capability + \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability + \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability + \arg RCU_LXTAL_HIGHDRI: higher driving capability + \param[out] none + \retval none +*/ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) +{ + uint32_t reg; + + reg = RCU_BDCTL; + + /* reset the LXTALDRI bits and set according to lxtal_dricap */ + reg &= ~RCU_BDCTL_LXTALDRI; + RCU_BDCTL = (reg | lxtal_dricap); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC48M stable */ + case RCU_IRC48M: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + +#ifdef GD32F30X_CL + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; +#endif /* GD32F30X_CL */ + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC48M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F30X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F30X_CL */ + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC48M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F30X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F30X_CL */ + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \arg 0x00 - 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & RCU_IRC8M_ADJUST_MASK) << RCU_IRC8M_ADJUST_OFFSET)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V + \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src, idx, clk_exp; +#ifdef GD32F30X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F30X_CL */ + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) { + /* PLL clock source is HXTAL or IRC48M */ + pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); + + if(RCU_PLLPRESRC_HXTAL == pllpresel){ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + }else{ + /* PLL clock source is IRC48 */ + ck_src = IRC48M_VALUE; + } + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE/2U; + } +#elif defined(GD32F30X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> RCU_CFG1_PREDV1_OFFSET) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> RCU_CFG1_PLL1MF_OFFSET) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src/predv1)*pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F30X_HD and GD32F30X_XD */ + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ + pllmf |= 0x20U; + } + if(pllmf < 15U){ + pllmf += 2U; + }else if((pllmf >= 15U) && (pllmf <= 62U)){ + pllmf += 1U; + }else{ + pllmf = 63U; + } + cksys_freq = ck_src*pllmf; + #ifdef GD32F30X_CL + if(15U == pllmf){ + cksys_freq = ck_src*6U + ck_src/2U; + } + #endif /* GD32F30X_CL */ + + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c new file mode 100644 index 0000000000..8fe1ef957f --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c @@ -0,0 +1,230 @@ +/*! + \file gd32f30x_rtc.c + \brief RTC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "gd32f30x_rtc.h" + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while (RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while (RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + temp = RTC_CNTL; + temp |= (RTC_CNTH << 16); + return temp; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = cnt >> 16; + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_VALUE); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = (psc & RTC_HIGH_VALUE) >> 16; + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_VALUE); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = alarm >> 16; + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_VALUE); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + temp = (RTC_DIVH & RTC_DIVH_DIV) << 16; + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c new file mode 100644 index 0000000000..b7b54ea9a6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c @@ -0,0 +1,809 @@ +/*! + \file gd32f30x_sdio.c + \brief SDIO driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_sdio.h" + +#define DEFAULT_RESET_VALUE 0x00000000U + +/*! + \brief deinitialize the SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_deinit(void) +{ + SDIO_PWRCTL = DEFAULT_RESET_VALUE; + SDIO_CLKCTL = DEFAULT_RESET_VALUE; + SDIO_CMDAGMT = DEFAULT_RESET_VALUE; + SDIO_CMDCTL = DEFAULT_RESET_VALUE; + SDIO_DATATO = DEFAULT_RESET_VALUE; + SDIO_DATALEN = DEFAULT_RESET_VALUE; + SDIO_DATACTL = DEFAULT_RESET_VALUE; + SDIO_INTC = DEFAULT_RESET_VALUE; + SDIO_INTEN = DEFAULT_RESET_VALUE; +} + +/*! + \brief configure the SDIO clock + \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: + \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK + \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK + \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass + \arg SDIO_CLOCKBYPASS_DISABLE: no bypass + \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle + \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on + \param[in] clock_division: clock division, less than 512 + \param[out] none + \retval none +*/ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division) +{ + uint32_t clock_config = 0U; + clock_config = SDIO_CLKCTL; + /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ + clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV8 | SDIO_CLKCTL_DIV); + /* if the clock division is greater or equal to 256, set the DIV[8] */ + if(clock_division >= 256U){ + clock_config |= SDIO_CLKCTL_DIV8; + clock_division -= 256U; + } + /* configure the SDIO_CLKCTL according to the parameters */ + clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division); + SDIO_CLKCTL = clock_config; +} + +/*! + \brief enable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief disable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief set different SDIO card bus mode + \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: + \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode + \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode + \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode + \param[out] none + \retval none +*/ +void sdio_bus_mode_set(uint32_t bus_mode) +{ + /* reset the SDIO card bus mode bits and set according to bus_mode */ + SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE; + SDIO_CLKCTL |= bus_mode; +} + +/*! + \brief set the SDIO power state + \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off + \param[out] none + \retval none +*/ +void sdio_power_state_set(uint32_t power_state) +{ + SDIO_PWRCTL = power_state; +} + +/*! + \brief get the SDIO power state + \param[in] none + \param[out] none + \retval SDIO power state + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off +*/ +uint32_t sdio_power_state_get(void) +{ + return SDIO_PWRCTL; +} + +/*! + \brief enable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN; +} + +/*! + \brief disable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN; +} + +/*! + \brief configure the command and response + \param[in] cmd_index: command index, refer to the related specifications + \param[in] cmd_argument: command argument, refer to the related specifications + \param[in] response_type: response type + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSETYPE_NO: no response + \arg SDIO_RESPONSETYPE_SHORT: short response + \arg SDIO_RESPONSETYPE_LONG: long response + \param[out] none + \retval none +*/ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) +{ + uint32_t cmd_config = 0U; + /* reset the command index, command argument and response type */ + SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; + SDIO_CMDAGMT = cmd_argument; + cmd_config = SDIO_CMDCTL; + cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP); + /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */ + cmd_config |= (cmd_index | response_type); + SDIO_CMDCTL = cmd_config; +} + +/*! + \brief set the command state machine wait type + \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: + \arg SDIO_WAITTYPE_NO: not wait interrupt + \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt + \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer + \param[out] none + \retval none +*/ +void sdio_wait_type_set(uint32_t wait_type) +{ + /* reset INTWAIT and WAITDEND */ + SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND); + /* set the wait type according to wait_type */ + SDIO_CMDCTL |= wait_type; +} + +/*! + \brief enable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN; +} + +/*! + \brief disable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; +} + +/*! + \brief get the last response command index + \param[in] none + \param[out] none + \retval last response command index +*/ +uint8_t sdio_command_index_get(void) +{ + return (uint8_t)SDIO_RSPCMDIDX; +} + +/*! + \brief get the response for the last received command + \param[in] responsex: SDIO response + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] + \arg SDIO_RESPONSE1: card response[95:64] + \arg SDIO_RESPONSE2: card response[63:32] + \arg SDIO_RESPONSE3: card response[31:1], plus bit 0 + \param[out] none + \retval response for the last received command +*/ +uint32_t sdio_response_get(uint32_t responsex) +{ + uint32_t resp_content = 0U; + switch(responsex){ + case SDIO_RESPONSE0: + resp_content = SDIO_RESP0; + break; + case SDIO_RESPONSE1: + resp_content = SDIO_RESP1; + break; + case SDIO_RESPONSE2: + resp_content = SDIO_RESP2; + break; + case SDIO_RESPONSE3: + resp_content = SDIO_RESP3; + break; + default: + break; + } + return resp_content; +} + +/*! + \brief configure the data timeout, data length and data block size + \param[in] data_timeout: data timeout period in card bus clock periods + \param[in] data_length: number of data bytes to be transferred + \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: + \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte + \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes + \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes + \arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes + \arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes + \arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes + \arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes + \arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes + \arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes + \arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes + \arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes + \arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes + \arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes + \arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes + \arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes + \param[out] none + \retval none +*/ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize) +{ + /* reset data timeout, data length and data block size */ + SDIO_DATATO &= ~SDIO_DATATO_DATATO; + SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN; + SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ; + /* configure the related parameters of data */ + SDIO_DATATO = data_timeout; + SDIO_DATALEN = data_length; + SDIO_DATACTL |= data_blocksize; +} + +/*! + \brief configure the data transfer mode and direction + \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSMODE_BLOCK: block transfer + \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer + \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSDIRECTION_TOCARD: write data to card + \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card + \param[out] none + \retval none +*/ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction) +{ + uint32_t data_trans = 0U; + /* reset the data transfer mode, transfer direction and set according to the parameters */ + data_trans = SDIO_DATACTL; + data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR); + data_trans |= (transfer_mode | transfer_direction); + SDIO_DATACTL = data_trans; +} + +/*! + \brief enable the DSM(data state machine) for data transfer + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DATAEN; +} + +/*! + \brief disable the DSM(data state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN; +} + +/*! + \brief write data(one word) to the transmit FIFO + \param[in] data: 32-bit data write to card + \param[out] none + \retval none +*/ +void sdio_data_write(uint32_t data) +{ + SDIO_FIFO = data; +} + +/*! + \brief read data(one word) from the receive FIFO + \param[in] none + \param[out] none + \retval received data +*/ +uint32_t sdio_data_read(void) +{ + return SDIO_FIFO; +} + +/*! + \brief get the number of remaining data bytes to be transferred to card + \param[in] none + \param[out] none + \retval number of remaining data bytes to be transferred +*/ +uint32_t sdio_data_counter_get(void) +{ + return SDIO_DATACNT; +} + +/*! + \brief get the number of words remaining to be written or read from FIFO + \param[in] none + \param[out] none + \retval remaining number of words +*/ +uint32_t sdio_fifo_counter_get(void) +{ + return SDIO_FIFOCNT; +} + +/*! + \brief enable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DMAEN; +} + +/*! + \brief disable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN; +} + +/*! + \brief get the flags state of SDIO + \param[in] flag: flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_CMDRUN: command transmission in progress flag + \arg SDIO_FLAG_TXRUN: data transmission in progress flag + \arg SDIO_FLAG_RXRUN: data reception in progress flag + \arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO + \arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO + \arg SDIO_FLAG_TFF: transmit FIFO is full flag + \arg SDIO_FLAG_RFF: receive FIFO is full flag + \arg SDIO_FLAG_TFE: transmit FIFO is empty flag + \arg SDIO_FLAG_RFE: receive FIFO is empty flag + \arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag + \arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_flag_get(uint32_t flag) +{ + if(RESET != (SDIO_STAT & flag)){ + return SET; + } + return RESET; +} + +/*! + \brief clear the pending flags of SDIO + \param[in] flag: flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_flag_clear(uint32_t flag) +{ + SDIO_INTC = flag; +} + +/*! + \brief enable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_enable(uint32_t int_flag) +{ + SDIO_INTEN |= int_flag; +} + +/*! + \brief disable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_disable(uint32_t int_flag) +{ + SDIO_INTEN &= ~int_flag; +} + +/*! + \brief get the interrupt flags state of SDIO + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt flag + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt flag + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt flag + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt flag + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt flag + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt flag + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt flag + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt flag + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt flag + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt flag + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt flag + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt flag + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt flag + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt flag + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt flag + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt flag + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt flag + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt flag + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt flag + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt flag + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt flag + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt flag + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt flag + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) +{ + if(RESET != (SDIO_STAT & int_flag)){ + return SET; + } + return RESET; +} + +/*! + \brief clear the interrupt pending flags of SDIO + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_interrupt_flag_clear(uint32_t int_flag) +{ + SDIO_INTC = int_flag; +} + +/*! + \brief enable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWEN; +} + +/*! + \brief disable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWEN; +} + +/*! + \brief enable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWSTOP; +} + +/*! + \brief disable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP; +} + +/*! + \brief set the read wait type(SD I/O only) + \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: + \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK + \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] + \param[out] none + \retval none +*/ +void sdio_readwait_type_set(uint32_t readwait_type) +{ + if(SDIO_READWAITTYPE_CLK == readwait_type){ + SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; + }else{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; + } +} + +/*! + \brief enable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_IOEN; +} + +/*! + \brief disable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_IOEN; +} + +/*! + \brief enable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief disable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief enable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN; +} + +/*! + \brief disable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN; +} + +/*! + \brief enable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_enable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN; +} + +/*! + \brief disable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_disable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN; +} + +/*! + \brief enable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief disable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c new file mode 100644 index 0000000000..6af0a4049a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c @@ -0,0 +1,859 @@ +/*! + \file gd32f30x_spi.c + \brief SPI driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_spi.h" + +#define SPI_ERROR_HANDLE(s) do{}while(1) + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* default value */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /*!< default value of SPI_I2SPSC register */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /*!< I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /*!< I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /*!< I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /*!< I2S clock division mask */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with default values + \param[in] none + \param[out] spi_parameter_struct: the initialized struct spi_parameter_struct pointer + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct *spi_struct) +{ + /* configure the structure with default value */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; + spi_struct->endian = SPI_ENDIAN_MSB; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] i2s_mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] i2s_standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] i2s_ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl) +{ + uint32_t reg= 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)i2s_mode; + /* select I2S standard */ + reg |= (uint32_t)i2s_standard; + /* select I2S polarity */ + reg |= (uint32_t)i2s_ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] i2s_audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] i2s_frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] i2s_mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + +#ifdef GD32F30X_CL + uint32_t pll2mf_4 = 0U; +#endif /* GD32F30X_CL */ + + /* judge whether the audiosample is 0 */ + if(0U == i2s_audiosample){ + SPI_ERROR_HANDLE("the parameter can not be 0 \r\n"); + } + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + +#ifdef GD32F30X_CL + /* get the I2S clock source */ + if(((uint32_t)spi_periph) == SPI1){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> 12U); + + pll2mf_4 = RCU_CFG1 & RCU_CFG1_PLL2MF_4; + + if( 0U == pll2mf_4){ + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 16 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + }else{ + if(clks < 15U){ + /* multiplier is between 18 and 32 */ + clks += 18U; + }else{ + if(15U == clks){ + /* multiplier is 40 */ + clks = 40U; + } + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> 4U) + 1U); + /* calculate i2sclock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } +#else + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); +#endif /* GD32F30X_CL */ + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == i2s_mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == i2s_frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / i2s_audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / i2s_audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | i2s_mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)i2s_frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA + \arg SPI_DMA_RECEIVE: SPI receive data use DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA + \arg SPI_DMA_RECEIVE: SPI receive data use DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* confige SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly) +{ + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} + +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI TI mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_ti_mode_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD; +} + +/*! + \brief disable SPI TI mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_ti_mode_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD); +} + +/*! + \brief enable SPI NSS pulse mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nssp_mode_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP; +} + +/*! + \brief disable SPI NSS pulse mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nssp_mode_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP); +} + +/*! + \brief enable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD; +} + +/*! + \brief disable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD); +} + +/*! + \brief enable quad wire SPI write + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_write_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD); +} + +/*! + \brief enable quad wire SPI read + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_read_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD; +} + +/*! + \brief enable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_io23_output_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV; +} + + /*! + \brief disable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ + void qspi_io23_output_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); +} + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI/I2S format error interrupt */ + case SPI_I2S_INT_FLAG_FERR: + reg1 = reg1 & SPI_STAT_FERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if(reg1 && reg2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + only one parameter can be selected which is shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg SPI_FLAG_FERR: format error flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \arg I2S_FLAG_FERR: format error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(SPI_STAT(spi_periph) & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c new file mode 100644 index 0000000000..47531ad495 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c @@ -0,0 +1,2042 @@ +/*! + \file gd32f30x_timer.c + \brief TIMER driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_timer.h" + +/*! + \brief deinit a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + case TIMER7: + /* reset TIMER7 */ + rcu_periph_reset_enable(RCU_TIMER7RST); + rcu_periph_reset_disable(RCU_TIMER7RST); + break; +#ifndef GD32F30X_HD + case TIMER8: + /* reset TIMER8 */ + rcu_periph_reset_enable(RCU_TIMER8RST); + rcu_periph_reset_disable(RCU_TIMER8RST); + break; + case TIMER9: + /* reset TIMER9 */ + rcu_periph_reset_enable(RCU_TIMER9RST); + rcu_periph_reset_disable(RCU_TIMER9RST); + break; + case TIMER10: + /* reset TIMER10 */ + rcu_periph_reset_enable(RCU_TIMER10RST); + rcu_periph_reset_disable(RCU_TIMER10RST); + break; + case TIMER11: + /* reset TIMER11 */ + rcu_periph_reset_enable(RCU_TIMER11RST); + rcu_periph_reset_disable(RCU_TIMER11RST); + break; + case TIMER12: + /* reset TIMER12 */ + rcu_periph_reset_enable(RCU_TIMER12RST); + rcu_periph_reset_disable(RCU_TIMER12RST); + break; + case TIMER13: + /* reset TIMER13 */ + rcu_periph_reset_enable(RCU_TIMER13RST); + rcu_periph_reset_disable(RCU_TIMER13RST); + break; +#endif /* GD32F30X_HD */ + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock, 0~65535 + alignedmode: TIMER_COUNTER_EDGE, TIMER_COUNTER_CENTER_DOWN, TIMER_COUNTER_CENTER_UP, TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP, TIMER_COUNTER_DOWN + period: counter auto reload value, 0~65535 + clockdivision: TIMER_CKDIV_DIV1, TIMER_CKDIV_DIV2, TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value, 0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) + || (TIMER3 == timer_periph) || (TIMER4 == timer_periph) || (TIMER7 == timer_periph)){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)(TIMER_CTL0_DIR|TIMER_CTL0_CAM); + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->alignedmode; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->counterdirection; + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CKDIV; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->clockdivision; + } + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] prescaler: prescaler value,0~65535 + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint8_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] repetition: the counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] autoreload: the counter auto-reload value,0~65535 + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] counter: the counter value,0~65535 + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint16_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..8,11) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt source disable + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: specify which DMA to enable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: specify which DMA to enable + one or more parameters can be selected which are shown as below: + \arg TIMER_DMA_UPD: update DMA ,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request ,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA request,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint8_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: please refer to the following parameters + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: please refer to the following parameters + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event,TIMERx(x=0..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation,TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation,TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation,TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation,TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation,TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation,TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_BRKG: break event generation,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate))| + ((uint32_t)(breakpara->ideloffstate))| + ((uint32_t)(breakpara->deadtime))| + ((uint32_t)(breakpara->breakpolarity))| + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode))| + ((uint32_t)(breakpara->breakstate))) ; +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief configure TIMER primary output function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint8_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = (uint16_t)TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); + } + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); + } + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); + } + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM0 mode + \arg TIMER_OC_MODE_PWM1: PWM1 mode + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] pulse: channel output pulse value,0~65535 + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \arg TIMER_CH_3: TIMER channel3 + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI,TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph,uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P|TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + /* read TIMER channel 0 capture compare register value */ + case TIMER_CH_0: + count_value = TIMER_CH0CV(timer_periph); + break; + /* read TIMER channel 1 capture compare register value */ + case TIMER_CH_1: + count_value = TIMER_CH1CV(timer_periph); + break; + /* read TIMER channel 2 capture compare register value */ + case TIMER_CH_2: + count_value = TIMER_CH2CV(timer_periph); + break; + /* read TIMER channel 3 capture compare register value */ + case TIMER_CH_3: + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \param[in] icpwm:TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channal0 as trigger output TRGO + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, + uint16_t ic0polarity, uint16_t ic1polarity) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS))&((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI|((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity|((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph, intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, + uint16_t extpolarity, uint32_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph,extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief configure TIMER write CHxVAL register selection + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[in] ccsel: + only one parameter can be selected which is shown as below: + \arg TIMER_CHVSEL_DISABLE: no effect + \arg TIMER_CHVSEL_ENABLE: when write the CHxVAL register, if the write value is same as the CHxVAL value, the write access is ignored + \param[out] none + \retval none +*/ +void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel) +{ + if(TIMER_CHVSEL_ENABLE == ccsel){ + TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_CHVSEL; + }else if(TIMER_CHVSEL_DISABLE == ccsel){ + TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_CHVSEL; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER output value selection + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] outsel: + only one parameter can be selected which is shown as below: + \arg TIMER_OUTSEL_DISABLE: no effect + \arg TIMER_OUTSEL_ENABLE: if POEN and IOS is 0, the output disabled + \param[out] none + \retval none +*/ +void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel) +{ + if(TIMER_OUTSEL_ENABLE == outsel){ + TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_OUTSEL; + }else if(TIMER_OUTSEL_DISABLE == outsel){ + TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_OUTSEL; + }else{ + /* illegal parameters */ + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c new file mode 100644 index 0000000000..42f6fe7990 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c @@ -0,0 +1,909 @@ +/*! + \file gd32f30x_usart.c + \brief USART driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_usart.h" + +/* USART register bit offset */ +#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */ +#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */ +#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */ + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk = rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & 0xfff0U; + fradiv = udiv & 0xfU; + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg ; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} + +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: enable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief data is transmitted/received with the LSB/MSB first + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] msbf: LSB/MSB + only one parameter can be selected which is shown as below: + \arg USART_MSBF_LSB: LSB first + \arg USART_MSBF_MSB: MSB first + \param[out] none + \retval none +*/ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); + USART_CTL3(usart_periph) |= msbf; +} + +/*! + \brief configure USART inversion + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] invertpara: refer to enum usart_invert_enum + only one parameter can be selected which is shown as below: + \arg USART_DINV_ENABLE: data bit level inversion + \arg USART_DINV_DISABLE: data bit level not inversion + \arg USART_TXPIN_ENABLE: TX pin level inversion + \arg USART_TXPIN_DISABLE: TX pin level not inversion + \arg USART_RXPIN_ENABLE: RX pin level inversion + \arg USART_RXPIN_DISABLE: RX pin level not inversion + \param[out] none + \retval none +*/ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) +{ + /* inverted or not the specified siginal */ + switch(invertpara){ + case USART_DINV_ENABLE: + /* data bit level inversion */ + USART_CTL3(usart_periph) |= USART_CTL3_DINV; + break; + case USART_TXPIN_ENABLE: + /* TX pin level inversion */ + USART_CTL3(usart_periph) |= USART_CTL3_TINV; + break; + case USART_RXPIN_ENABLE: + /* RX pin level inversion */ + USART_CTL3(usart_periph) |= USART_CTL3_RINV; + break; + case USART_DINV_DISABLE: + /* data bit level not inversion */ + USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); + break; + case USART_TXPIN_DISABLE: + /* TX pin level not inversion */ + USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); + break; + case USART_RXPIN_DISABLE: + /* RX pin level not inversion */ + USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); + break; + default: + break; + } +} + +/*! + \brief enable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_enable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) |= USART_CTL3_RTEN; +} + +/*! + \brief disable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_disable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN); +} + +/*! + \brief set the receiver timeout threshold of USART + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] rtimeout: 0-0xFFFFFF + \param[out] none + \retval none +*/ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout) +{ + USART_RT(usart_periph) &= ~(USART_RT_RT); + USART_RT(usart_periph) |= rtimeout; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint32_t data) +{ + USART_DATA(usart_periph) = ((uint16_t)USART_DATA_DATA & data); +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] guat: guard time value, 0-0xFF + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((guat)<> 8);(uint8_t)((x) >> 16) + +/* audio_freq * data_size (2 bytes) * num_channels (stereo: 2) */ +#define DEFAULT_OUT_BIT_RESOLUTION 16U +#define DEFAULT_OUT_CHANNEL_NBR 2U /* mono = 1, stereo = 2 */ +#define AUDIO_OUT_PACKET (uint32_t)(((USBD_AUDIO_FREQ_16K * \ + (DEFAULT_OUT_BIT_RESOLUTION / 8U) *\ + DEFAULT_OUT_CHANNEL_NBR) / 1000U)) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((AUDIO_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN 109U +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x0001U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_CUR 0x01U + +#define AUDIO_OUT_STREAMING_CTRL 0x02U + +#define PACKET_SIZE(freq) (((freq) * 2U) * 2U / 1000U) + +#define AUDIO_PACKET_SIZE(frq) (uint8_t)(PACKET_SIZE(frq) & 0xFFU), \ + (uint8_t)((PACKET_SIZE(frq) >> 8U) & 0xFFU) + +#define SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq) >> 8U), \ + (uint8_t)((frq) >> 16U) + + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ + uint8_t baInterfaceNr; /*!< interface number of the streaming interfaces */ +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio sub-frame */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio sub-frame */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + usb_desc_input_terminal in_terminal; + usb_desc_mono_feature_unit feature_unit; + usb_desc_output_terminal out_terminal; + usb_desc_itf std_as_itf_zeroband; + usb_desc_itf std_as_itf_opera; + usb_desc_AS_itf as_itf; + usb_desc_format_type format_typeI; + usb_desc_std_ep std_endpoint; + usb_desc_AS_ep as_endpoint; +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + + uint32_t play_flag; +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class audio_class; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..0ef370cfc3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c new file mode 100644 index 0000000000..c15eeca223 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c @@ -0,0 +1,549 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "audio_out_itf.h" +#include "audio_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +/* local function prototypes ('static') */ +static uint8_t usbd_audio_sof (usb_dev *udev); +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static void audio_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class audio_class = { + .init = audio_init, + .deinit = audio_deinit, + .req_process = audio_req_handler, + .ctlx_out = audio_ctlx_out, + .data_out = audio_data_out +}; + +usbd_int_cb_struct usb_inthandler = +{ + usbd_audio_sof, +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = 0x0027U, + .bInCollection = 0x01U, + .baInterfaceNr = 0x01U + }, + + .in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x01U, + .wChannelConfig = 0x0000U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = 0x00U, + .iFeature = 0x00U + }, + + .out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, + + .std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x01U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_III, + .bNrChannels = 0x02U, + .bSubFrameSize = 0x02U, + .bBitResolution = 0x10U, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_AUDIO_FREQ_16K, + .bSamFreq[1] = USBD_AUDIO_FREQ_16K >> 8, + .bSamFreq[2] = USBD_AUDIO_FREQ_16K >> 16 + }, + + .std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = PACKET_SIZE(USBD_AUDIO_FREQ_16K), + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static uint8_t* usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + + +/*! + \brief initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + usb_desc_std_ep std_ep = audio_config_set.std_endpoint; + + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_init(udev, EP_BUF_DBL, AUDIO_BUF_ADDR, &ep); + + usbd_int_fops = &usb_inthandler; + + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + udev->ep_transc[AUDIO_OUT_EP][TRANSC_OUT] = audio_class.data_out; + + /* prepare out endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, (uint16_t)AUDIO_OUT_PACKET); + + udev->class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize audio endpoints */ + usbd_ep_deinit(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle the audio class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + usb_transc_config(&udev->transc_in[0], audio->audioctl, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + usb_transc_config(&udev->transc_out[0], audio->audioctl, req->wLength, 0U); + + udev->class_core->req_cmd = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handles the audio out data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void audio_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + if (AUDIO_OUT_EP == ep_num) { + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += AUDIO_OUT_PACKET; + } + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), (uint16_t)AUDIO_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((AUDIO_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } + } +} + +/*! + \brief handles audio control request data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->class_core->req_cmd) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->class_core->req_cmd = 0U; + + audio->audioctl_len = 0U; + } + } + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += AUDIO_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..7e55fdcf7a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c @@ -0,0 +1,242 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + uint8_t status = AUDIO_OK; + + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, (size / 2U)); + audio_state = AUDIO_STATE_PLAYING; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + } + } else { + status = AUDIO_FAIL; + } + break; + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + } + break; + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + } + break; + + /* unsupported command */ + default: + break; + } + + return status; +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + /* call low layer volume setting function */ + if (eval_audio_volume_ctl(vol)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + /* call low layer mute setting function */ + if (eval_audio_mute((uint32_t)cmd)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..930e93dc80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h @@ -0,0 +1,163 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* CDC subclass code */ +#define USB_CDC_SUBCLASS_DLCM 0x01U +#define USB_CDC_SUBCLASS_ACM 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for PSTN subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#pragma pack(1) + +/* CDC ACM line coding struct */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +/* header function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +/* call managment function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +/* acm function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +/* union function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() +/* configuration descriptor struct */ +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#define USB_CDC_RX_LEN 64U + +typedef struct { + uint8_t pre_packet_send; + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class cdc_class; + +/* function declarations */ +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* check cdc acm is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..3f8d8409b5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c @@ -0,0 +1,510 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CDC_ACM_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = { + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num); +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class cdc_class = { + .req_cmd = NO_CMD, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_process = cdc_acm_req_handler, + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_data_in, + .data_out = cdc_acm_data_out +}; + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive(usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->pre_packet_send = 0U; + + usbd_ep_recev(udev, CDC_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_RX_LEN); +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + uint32_t data_len = cdc->receive_length; + + if ((0U != data_len) && (1U == cdc->packet_sent)) { + cdc->packet_sent = 0U; + usbd_ep_send(udev, CDC_IN_EP, (uint8_t*)(cdc->data), (uint16_t)data_len); + cdc->receive_length = 0U; + } +} + +/*! + \brief check cdc acm is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 otherwise +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->pre_packet_send)) { + return 0U; + } + } + + return 5U; +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(cdc_config_desc.cdc_in_endpoint)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(cdc_config_desc.cdc_cmd_endpoint)); + + udev->ep_transc[EP_ID(CDC_IN_EP)][TRANSC_IN] = cdc_class.data_in; + udev->ep_transc[CDC_OUT_EP][TRANSC_OUT] = cdc_class.data_out; + + /* initialize cdc handler structure */ + cdc_handler.packet_receive = 0U; + cdc_handler.packet_sent = 1U; + cdc_handler.pre_packet_send = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200U, + .bCharFormat = 0U, + .bParityType = 0U, + .bDataBits = 0x08U + }; + + udev->class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data endpoints */ + usbd_ep_deinit(udev, CDC_IN_EP); + usbd_ep_deinit(udev, CDC_OUT_EP); + + /* deinitialize the command endpoint */ + usbd_ep_deinit(udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief command data received on control endpoint + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (NO_CMD != udev->class_core->req_cmd) { + cdc->packet_receive = 1U; + cdc->pre_packet_send = 1U; + + udev->class_core->req_cmd = NO_CMD; + } + + return USBD_OK; +} + + +/*! + \brief handle CDC ACM data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->transc_in[ep_num]; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (transc->xfer_count == transc->max_len) { + usbd_ep_send(udev, EP_ID(ep_num), NULL, 0U); + } else { + cdc->packet_sent = 1U; + cdc->pre_packet_send = 1U; + } +} + +/*! + \brief handle CDC ACM data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + + cdc->receive_length = udev->transc_out[ep_num].xfer_count; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP, noti_buf[10] = {0U}; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + acm_notification *notif = (void *)noti_buf; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + break; + + case GET_ENCAPSULATED_RESPONSE: + break; + + case SET_COMM_FEATURE: + break; + + case GET_COMM_FEATURE: + break; + + case CLEAR_COMM_FEATURE: + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->class_core->req_cmd = req->bRequest; + + usb_transc_config(&udev->transc_out[0U], (uint8_t *)&cdc->line_coding, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case GET_LINE_CODING: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&cdc->line_coding, 7U, 0U); + + status = REQ_SUPP; + break; + + case SET_CONTROL_LINE_STATE: + notif->bmRequestType = 0xA1U; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wIndex = 0U; + notif->wValue = 0U; + notif->wLength = 2U; + noti_buf[8] = (uint8_t)req->wValue & 3U; + noti_buf[9] = 0U; + + status = REQ_SUPP; + break; + + case SEND_BREAK: + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..933fb3bf64 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h @@ -0,0 +1,179 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) do { \ + dfu->bwPollTimeout0 = _BYTE1(x);\ + dfu->bwPollTimeout1 = _BYTE2(x);\ + dfu->bwPollTimeout2 = _BYTE3(x);\ + } while(0) + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) +#define USB_DFU_CONFIG_DESC_SIZE (18U + (9U * USBD_ITF_MAX_NUM)) +#define DFU_DESC_TYPE 0x21U + +/* DFU device state enumeration */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status enumeration */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests enumeration */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor struct */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor struct */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +/* USB DFU handler struct */ +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class dfu_class; + +#endif /* __DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..c1e42597b4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c @@ -0,0 +1,674 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "systick.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in (usb_dev *udev); + +/* DFU requests management functions */ +static void dfu_detach (usb_dev *udev, usb_req *req); +static void dfu_dnload (usb_dev *udev, usb_req *req); +static void dfu_upload (usb_dev *udev, usb_req *req); +static void dfu_getstatus (usb_dev *udev, usb_req *req); +static void dfu_clrstatus (usb_dev *udev, usb_req *req); +static void dfu_getstate (usb_dev *udev, usb_req *req); +static void dfu_abort (usb_dev *udev, usb_req *req); +static void dfu_mode_leave (usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x00U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB config string */ +static usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +uint8_t* usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_process = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + fmc_unlock(); + + systick_config(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the USB DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief handle data in stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + fmc_page_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* preform the write operation */ + uint32_t idx = 0U; + + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + if (dfu->data_len & 0x03U) { /* not an aligned data */ + for (idx = dfu->data_len; idx < ((dfu->data_len & 0xFFFCU) + 4U); idx++) { + dfu->buf[idx] = 0xFFU; + } + } + + /* data received are word multiple */ + for (idx = 0U; idx < dfu->data_len; idx += 4U) { + fmc_word_program(addr, *(uint32_t *)(dfu->buf + idx)); + + addr += 4U; + } + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (STATE_DFU_MANIFEST == dfu->bState) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect(udev); + + usbd_connect(udev); + } else { + /* wait for the period of time specified in detach request */ + delay_1ms(4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_out[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->xfer_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + transc->xfer_count = 0U; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + + return; + } + + usb_transc *transc = &udev->transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->xfer_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = (uint8_t *)(addr); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->xfer_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + SET_POLLING_TIMEOUT(FLASH_ERASE_TIMEOUT); + } else { + SET_POLLING_TIMEOUT(FLASH_WRITE_TIMEOUT); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->xfer_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->xfer_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..b650f0738c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h @@ -0,0 +1,67 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class custom_hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..1b00045a61 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h @@ -0,0 +1,66 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send HID report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h new file mode 100644 index 0000000000..91a5f5f20d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h @@ -0,0 +1,69 @@ +/*! + \file std_hid_mouse_core.h + \brief definitions for HID mouse core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STD_HID_MOUSE_CORE_H +#define __STD_HID_MOUSE_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x34U + +#define MOUSE_LEFT_BUTTON 0x01U +#define MOUSE_RIGHT_BUTTON 0x02U + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_mice_handler; + +typedef struct { + void (*mice_itf_config) (void); + void (*mice_itf_data_process) (usb_dev *udev); +} mice_fop_handler; + +extern usb_desc hid_mouse_desc; +extern usb_class hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, mice_fop_handler *hid_fop); +/* send mouse report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __STD_HID_MOUSE_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h new file mode 100644 index 0000000000..0492ceec80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +} usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..a85e6af72d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c @@ -0,0 +1,503 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "custom_hid_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class custom_hid_class = { + .req_cmd = 0xFFU, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + .req_process = custom_hid_req_handler, + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] pudev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(custom_hid_handler)); + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, HID_TX_ADDR, &(custom_hid_config_desc.hid_epin)); + usbd_ep_init(udev, EP_BUF_SNG, HID_RX_ADDR, &(custom_hid_config_desc.hid_epout)); + + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->ep_transc[EP_ID(CUSTOMHID_IN_EP)][TRANSC_IN] = custom_hid_class.data_in; + udev->ep_transc[EP_ID(CUSTOMHID_OUT_EP)][TRANSC_OUT] = custom_hid_class.data_out; + + udev->class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit(udev, CUSTOMHID_IN_EP); + usbd_ep_deinit(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)customhid_report_descriptor, + USB_MIN(DESC_LEN_REPORT, req->wLength), + 0U); + + status = REQ_SUPP; + } + break; + + case GET_REPORT: + if (2U == req->wLength) { + usb_transc_config(&udev->transc_in[0], hid->data, 2U, 0U); + + status = REQ_SUPP; + } + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], hid->data, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle custom HID data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return; +} + +/*! + \brief handle custom HID data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + if (CUSTOMHID_OUT_EP == ep_num){ + + switch (hid->data[0]){ + case 0x11: + if (RESET != hid->data[1]) { + /* turn on led1 */ + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + case 0x12: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + case 0x13: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + case 0x14: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + default: + /* turn off all leds */ + gd_eval_led_off(LED5); + gd_eval_led_off(LED2); + gd_eval_led_off(LED3); + gd_eval_led_off(LED4); + break; + } + + usbd_ep_recev(udev, CUSTOMHID_IN_EP, hid->data, 2U); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..373810b6b7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c @@ -0,0 +1,427 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "standard_hid_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, +#ifdef LPM_ENABLED + .bcdUSB = 0x0201U, +#else + .bcdUSB = 0x0200U, +#endif /* LPM_ENABLED */ + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +#ifdef LPM_ENABLED + +/* BOS descriptor */ +uint8_t USBD_BOSDesc[USB_BOS_DESC_LEN] = +{ + 0x05, + USB_DESCTYPE_BOS, + 0x0C, + 0x00, + 0x01, /* 1 device capability descriptor */ + + /* device capability*/ + 0x07, + USB_DEVICE_CAPABITY, + 0x02, + 0x06, /* LPM capability bit set */ + 0x00, + 0x00, + 0x00 +}; + +#endif /* LPM_ENABLED */ + +usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { +#ifdef LPM_ENABLED + .bos_desc = (uint8_t *)&USBD_BOSDesc, +#endif /* LPM_ENABLED */ + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req); +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num); + +usb_class hid_class = { + .init = hid_init, + .deinit = hid_deinit, + .req_process = hid_req_handler, + .data_in = hid_data_in_handler +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + /* check if USB is configured */ + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(standard_hid_handler)); + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(hid_config_desc.hid_epin)); + + udev->ep_transc[EP_ID(HID_IN_EP)][TRANSC_IN] = hid_class.data_in; + + hid_handler.prev_transfer_complete = 1U; + + udev->class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->user_data) { + ((hid_fop_handler *)udev->user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->idle_state, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)hid_report_desc, + USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength), + 0U); + + status = REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)(&(hid_config_desc.hid_vendor)), + USB_MIN(9U, req->wLength), + 0U); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data stage in DATA IN transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if (hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c new file mode 100644 index 0000000000..6ac896d475 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c @@ -0,0 +1,425 @@ +/*! + \file std_hid_mouse_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "std_hid_mouse_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0381U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, +#ifdef LPM_ENABLED + .bcdUSB = 0x0201U, +#else + .bcdUSB = 0x0200U, +#endif /* LPM_ENABLED */ + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +#ifdef LPM_ENABLED + +/* BOS descriptor */ +uint8_t USBD_BOSDesc[USB_BOS_DESC_LEN] = +{ + 0x05, + USB_DESCTYPE_BOS, + 0x0C, + 0x00, + 0x01, /* 1 device capability descriptor */ + + /* device capability*/ + 0x07, + USB_DEVICE_CAPABITY, + 0x02, + 0x06, /* LPM capability bit set */ + 0x00, + 0x00, + 0x00 +}; + +#endif /* LPM_ENABLED */ + +usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_MOUSE, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'o', 'u', 's', 'e'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +static uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_mouse_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req); + +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num); + +usb_class hid_class = { + .init = hid_init, + .deinit = hid_deinit, + .req_process = hid_req_handler, + .data_in = hid_data_in_handler +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x09, 0x01, /* USAGE (Pointer) */ + + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ + + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x38, /* USAGE (Wheel) */ + + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0xc0, /* END_COLLECTION */ + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, mice_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send mouse report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + standard_mice_handler *hid = (standard_mice_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if(udev->cur_status == USBD_CONFIGURED){ + if(1U == hid->prev_transfer_complete){ + hid->prev_transfer_complete = 0U; + usbd_ep_send(udev, HID_IN_EP, report, len); + } + } + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_mice_handler mice_handler; + + memset((void *)&mice_handler, 0, sizeof(standard_mice_handler)); + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(hid_config_desc.hid_epin)); + + udev->ep_transc[EP_ID(HID_IN_EP)][TRANSC_IN] = hid_class.data_in; + + mice_handler.prev_transfer_complete = 1U; + + udev->class_data[USBD_HID_INTERFACE] = (void *)&mice_handler; + + if (NULL != udev->user_data) { + ((mice_fop_handler *)(udev->user_data))->mice_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + standard_mice_handler *hid = (standard_mice_handler *)udev->class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->idle_state, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)hid_report_desc, + USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength), + 0U); + + status = REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data stage in DATA IN transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num) +{ + standard_mice_handler *hid = (standard_mice_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if(hid->data[0] == 0U){ + hid->prev_transfer_complete = 1U; + }else{ + hid->data[0] = 0U; + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..d9f7a8aa7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h @@ -0,0 +1,82 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_DESC_LEN_IAP_REPORT 35U +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U + +typedef void (*app_func) (void); + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +extern usb_desc iap_desc; +extern usb_class iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send(usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..093214e9d0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c @@ -0,0 +1,594 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "usb_iap_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028BU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev iap_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +usb_hid_desc_config_set iap_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x01U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +uint8_t* usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static void iap_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_process = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x3f, /* REPORT_COUNT (63) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x10, /* REPORT_COUNT (16) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len); + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_iap_handler iap_handler; + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_RX_ADDR, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0, sizeof(usbd_iap_handler)); + + /* prepare receive Data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + udev->ep_transc[EP_ID(IAP_OUT_EP)][TRANSC_OUT] = iap_class.data_out; + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, IAP_IN_EP); + usbd_ep_deinit (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], iap->report_buf, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)iap_report_desc, + USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength), + 0U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch(iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE: + iap_req_optionbyte(udev); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); +} + +/*! + \brief send iap report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload (usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase (usb_dev *udev) +{ + uint32_t i, addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= (uint32_t)iap->report_buf[3] << 8; + iap->base_address |= (uint32_t)iap->report_buf[4] << 16; + iap->base_address |= (uint32_t)iap->report_buf[5] << 24; + + iap->page_count = iap->report_buf[6]; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= (uint32_t)iap->report_buf[8] << 8; + iap->file_length |= (uint32_t)iap->report_buf[9] << 16; + iap->file_length |= (uint32_t)iap->report_buf[10] << 24; + + /* compute last packet size and transfer times */ + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + for (i = 0U; i < iap->page_count; i ++) { + /* call the standard flash erase-page function */ + fmc_page_erase(addr); + + addr += PAGE_SIZE; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_optionbyte (usb_dev *udev) +{ + uint8_t i = 0U; + uint32_t address = 0x1FFFF800U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0] = 0x02U; + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send(udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave (usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} + +/*! + \brief write data to sectors of memory + \param[in] data: data to be written + \param[in] addr: sector address/code + \param[in] len: length of data to be written (in bytes) + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len) +{ + uint32_t index = 0U; + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return; + } + + if (len & 0x03U) {/* not an aligned data */ + for (index = len; index < ((len & 0xFFFCU) + 4U); index++) { + data[index] = 0xFFU; + } + } + + /* data received are word multiple */ + for (index = 0U; index < len; index += 4U) { + fmc_word_program(addr, *(uint32_t *)(data + index)); + addr += 4U; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..24518f078a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,130 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +// uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_dev *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_dev *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_dev *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..cd624dbda5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h @@ -0,0 +1,86 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +/* mass storage class-specific request codes */ +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..db125424b3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..91891ec110 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h @@ -0,0 +1,60 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..308cf2d807 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,127 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" + +#define SENSE_LIST_DEEPTH 4U + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_dev *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..7246c11071 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,284 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_dev *udev); +static void msc_bbb_data_send (usb_dev *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_dev *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_dev *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint16_t rx_len = udev->transc_out[MSC_OUT_EP].xfer_count; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != rx_len) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_dev *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..bd8b26eafa --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c @@ -0,0 +1,316 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include "usbd_transc.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static void msc_core_in (usb_dev *udev, uint8_t ep_num); +static void msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_process = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev msc_dev_desc = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set msc_config_desc = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static uint8_t usbd_msc_maxlun = 0U; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_msc_handler msc_handler; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(msc_config_desc.msc_epin)); + + /* initialize Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(msc_config_desc.msc_epout)); + + udev->ep_transc[EP_ID(MSC_IN_EP)][TRANSC_IN] = msc_class.data_in; + udev->ep_transc[MSC_OUT_EP][TRANSC_OUT] = msc_class.data_out; + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_deinit (udev, MSC_IN_EP); + usbd_ep_deinit (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + usb_transc_config(&udev->transc_in[0], &usbd_msc_maxlun, 1U, 0U); + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..9e81754c1e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c @@ -0,0 +1,74 @@ +/*! + \file msc_bbb_scsi.h + \brief the header file of the msc_bbb_scsi.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..25152de1c7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,729 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun); +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_dev *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + +// if (1U == msc->scsi_disk_pop) { +// usbd_disconnect (udev); +// } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; +// msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h new file mode 100644 index 0000000000..98b2ee4fe0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h @@ -0,0 +1,73 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +extern usb_desc printer_desc; +extern usb_class printer_class; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c new file mode 100644 index 0000000000..720bda45cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t Printer_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req); +static void printer_data_in (usb_dev *udev, uint8_t ep_num); +static void printer_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class printer_class = { + .init = printer_init, + .deinit = printer_deinit, + .req_process = printer_req_handler, + .data_in = printer_data_in, + .data_out = printer_data_out +}; +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx/Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(printer_config_desc.printer_epin)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(printer_config_desc.printer_epout)); + + udev->ep_transc[EP_ID(PRINTER_IN_EP)][TRANSC_IN] = printer_class.data_in; + udev->ep_transc[PRINTER_OUT_EP][TRANSC_OUT] = printer_class.data_out; + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief de-initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_deinit(udev, PRINTER_IN_EP); + usbd_ep_deinit(udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + switch (req->bRequest) { + case GET_DEVICE_ID: + usb_transc_config(&udev->transc_in[0], Printer_DEVICE_ID, DEVICE_ID_LEN, 0U); + + status = REQ_SUPP; + break; + + case GET_PORT_STATUS: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&g_port_status, 1U, 0U); + + status = REQ_SUPP; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_in (usb_dev *udev, uint8_t ep_num) +{ +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_out (usb_dev *udev, uint8_t ep_num) +{ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h new file mode 100644 index 0000000000..7ba1d3d08e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h @@ -0,0 +1,212 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usbd_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_BOS_DESC_LEN 0x0CU /*!< USB BOS descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB SETUP packet length */ +#define USB_DEVICE_CAPABITY 0x10U /*!< USB device capabity */ + + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, /*!< USB reserved2 */ + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, /*!< USB reserved4 */ + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronized frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB endpoint descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB endpoint control attributes*/ + USB_EP_ATTR_ISO = 0x1U, /*!< USB endpoint isochronous attributes*/ + USB_EP_ATTR_BULK = 0x2U, /*!< USB endpoint bulk attributes*/ + USB_EP_ATTR_INT = 0x3U /*!< USB endpoint interrupt attributes*/ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< USB endpoint no SYNC attributes*/ +#define USB_EP_ATTR_ASYNC 0x04U /*!< USB endpoint ASYNC attributes*/ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< USB endpoint adaptive attributes*/ +#define USB_EP_ATTR_SYNC 0x0CU /*!< USB endpoint SYNC attributes*/ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< USB endpoint SYNC type attributes*/ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< USB endpoint data attributes*/ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< USB endpoint feedback attributes*/ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< USB endpoint implicit feedback attributes*/ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< USB endpoint usage type attributes*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet definition */ +typedef union _usb_setup { + uint8_t data[8]; /*!< USB setup data */ + + usb_req req; /*!< USB setup request */ +} usb_setup; + +/* USB descriptor definition */ +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t wTotalLength; /*!< size of the configuration descriptor header, and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attribute */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h new file mode 100644 index 0000000000..138880172e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h @@ -0,0 +1,332 @@ +/*! + \file usbd_core.h + \brief USB device driver core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "usb_ch9_std.h" + +/* endpoints definitions */ +#define EP_IN(x) ((uint8_t)(0x80U | (x))) +#define EP_OUT(x) ((uint8_t)(x)) + +#define EP_DIR(x) ((uint8_t)((x) >> 7U)) +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) + +/* USB device endpoint0 max packet size */ +#define USBD_EP0_MAX_SIZE 64U + +#define USBD_TRANSC_COUNT 3U + +/* USB device operation status */ +enum usbd_status { + USBD_UNCONNECTED = 0U, /*!< USB device unconnected status */ + USBD_DEFAULT, /*!< USB device default status */ + USBD_ADDRESSED, /*!< USB device addressed status */ + USBD_CONFIGURED, /*!< USB device configured status */ + USBD_SUSPENDED, /*!< USB device suspended status */ + USBD_CONNECTED /*!< USB device connected status */ +}; + +/* USB device operation state */ +enum usbd_state { + USBD_OK = 0U, /*!< USB device OK state */ + USBD_BUSY, /*!< USB device busy state */ + USBD_FAIL /*!< USB device fail state */ +}; + +/* USB device transaction type */ +enum usbd_transc { + TRANSC_SETUP = 0U, /*!< SETUP transaction */ + TRANSC_OUT, /*!< OUT transaction */ + TRANSC_IN, /*!< IN transaction */ + TRANSC_UNKNOWN /*!< unknown transaction */ +}; + +/* USB device endpoint buffer type */ +enum usbd_ep_kind { + EP_BUF_SNG = 0U, /*!< single buffer endpoint type value */ + EP_BUF_DBL /*!< double buffer endpoint type value */ +}; + +/* USB device transaction struct */ +typedef struct { + uint8_t max_len; /*!< packet max length */ + uint8_t ep_stall; /*!< endpoint STALL */ + + uint8_t *xfer_buf; /*!< transfer buffer */ + uint16_t xfer_len; /*!< transfer length */ + uint16_t xfer_count; /*!< transfer count */ +} usb_transc; + +/* USB device basic struct */ +typedef struct { + uint8_t max_ep_count; /*!< endpoint max count */ + uint8_t twin_buf; /*!< double buffer */ + uint16_t ram_size; /*!< ram size */ +} usb_basic; + +/* USB descriptor */ +typedef struct { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< bos descriptor */ + uint8_t **strings; /*!< strings descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t esof_count; /*!< ESOF count */ + uint8_t suspend_enabled; /*!< suspend enabled flag */ + uint8_t remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup enable */ + uint8_t lpm_enable; /*!< LPM enable */ +} usb_pm; + +/* USB LPM management */ +typedef struct { + uint32_t besl; /*!< besl */ + uint32_t L1_resume; /*!< L1 resume */ + uint32_t L1_remote_wakeup; /*!< L1 remote wakeup */ +} usb_lpm; + +/* USB control information */ +typedef struct { + usb_req req; /*!< USB request */ + uint8_t ctl_zlp; /*!< control zero length packet */ +} usb_control; + +typedef struct _usb_dev usb_dev; +typedef struct _usb_handler usb_handler; +typedef void (*usb_ep_transc) (usb_dev *usbd_dev, uint8_t ep_num); + +/* USB class struct */ +typedef struct { + uint8_t req_cmd; + uint8_t req_altset; + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); + + uint8_t (*req_process) (usb_dev *udev, usb_req *req); + + uint8_t (*ctlx_in) (usb_dev *udev); + uint8_t (*ctlx_out) (usb_dev *udev); + + void (*data_in) (usb_dev *udev, uint8_t ep_num); + void (*data_out) (usb_dev *udev, uint8_t ep_num); +} usb_class; + +/* USB core driver struct */ +struct _usb_dev { + /* basic parameters */ + uint8_t config; + uint8_t dev_addr; + + __IO uint8_t cur_status; + __IO uint8_t backup_status; + + usb_pm pm; +#ifdef LPM_ENABLED + usb_lpm lpm; +#endif /* LPM_ENABLED */ + usb_control control; + + usb_transc transc_out[EP_COUNT]; + usb_transc transc_in[EP_COUNT]; + + usb_ep_transc ep_transc[EP_COUNT][USBD_TRANSC_COUNT]; + + /* device class */ + usb_desc *desc; + usb_class *class_core; + usb_handler *drv_handler; + + void *class_data[USBD_ITF_MAX_NUM]; + void *user_data; + void *data; +}; + +typedef struct +{ + uint8_t (*SOF) (usb_dev *udev); /*!< SOF ISR callback */ +} usbd_int_cb_struct; + +/* USB handler struct */ +struct _usb_handler { + void (*init) (void); + void (*deinit) (void); + + void (*dp_pullup) (FlagStatus status); + void (*set_addr) (usb_dev *udev); + void (*suspend) (void); + void (*suspend_leave) (void); + void (*resume) (usb_dev *udev); + + void (*ep_reset) (usb_dev *udev); + void (*ep_setup) (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); + void (*ep_disable) (usb_dev *udev, uint8_t ep_addr); + void (*ep_rx_enable) (usb_dev *udev, uint8_t ep_num); + void (*ep_write) (uint8_t *fifo, uint8_t ep_num, uint16_t bytes); + uint16_t (*ep_read) (uint8_t *fifo, uint8_t ep_num, uint8_t buf_kind); + void (*ep_stall_set) (usb_dev *udev, uint8_t ep_addr); + void (*ep_stall_clear) (usb_dev *udev, uint8_t ep_addr); + uint8_t (*ep_status_get) (usb_dev *udev, uint8_t ep_addr); +}; + +extern usbd_int_cb_struct *usbd_int_fops; + +/* static inline function definitions */ +/*! + \brief device connect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_connect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(SET); + + udev->cur_status = (uint8_t)USBD_CONNECTED; +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_disconnect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(RESET); + + udev->cur_status = (uint8_t)USBD_UNCONNECTED; +} + +/*! + \brief device core register configure when stop device + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_core_deinit (usb_dev *udev) +{ + udev->drv_handler->deinit(); +} + +/*! + \brief initialize endpoint + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: buffer addresss + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_init (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + udev->drv_handler->ep_setup(udev, buf_kind, buf_addr, ep_desc); +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_deinit (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_disable(udev, ep_addr); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_set(udev, ep_addr); +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_clear_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_clear(udev, ep_addr); +} + +/*! + \brief get endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usbd_ep_status_get (usb_dev *udev, uint8_t ep_addr) +{ + return udev->drv_handler->ep_status_get(udev, ep_addr); +} + +/* function declarations */ +/* initialize USBD */ +void usbd_init(usb_dev *udev, usb_desc *desc, usb_class *usbc); +/* endpoint prepare to transmit data */ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); +/* endpoint prepare to receive data */ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h new file mode 100644 index 0000000000..da6238bb99 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h @@ -0,0 +1,111 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usb_ch9_std.h" + +#ifndef NULL + #define NULL 0U +#endif + +/* request state enumeration */ +typedef enum _usb_reqsta +{ + REQ_SUPP = 0x0U, /* supported request */ + REQ_NOTSUPP = 0x1U /* unsupported request */ +} usb_reqsta; + +/* string descriptor index enumeration */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ + STR_IDX_MAX = 0x6U /* string index max value */ +}; + +/* PWR status enumeration */ +typedef enum +{ + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +/* usb endpoint feature enumeration */ +typedef enum +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* device unique ID */ +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) /* device ID information */ + +//#define USB_SERIAL_STRING_SIZE 0x1AU + +/* USB device exported macros */ +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req); +/* handle device class request */ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h new file mode 100644 index 0000000000..84a31fc788 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h @@ -0,0 +1,67 @@ +/*! + \file usbd_pwr.h + \brief USB device power management functions prototype + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_PWR_H +#define __USBD_PWR_H + +#include "usbd_core.h" + +/* static inline function definitions */ +/*! + \brief first operation of USB wakeup is to wakeup MCU + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void resume_mcu (usb_dev *udev) +{ + udev->drv_handler->suspend_leave(); +} + +/*! + \brief set USB device to suspend mode + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_to_suspend (usb_dev *udev) +{ + udev->drv_handler->suspend(); +} + +/* function declarations */ +/* start to remote wakeup */ +void usbd_remote_wakeup_active (usb_dev *udev); + +#endif /* __USBD_PWR_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h new file mode 100644 index 0000000000..e60da374e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h @@ -0,0 +1,63 @@ +/*! + \file usbd_transc.h + \brief USBD transaction + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_TRANSC_H +#define __USB_TRANSC_H + +#include "usbd_core.h" + +/*! + \brief USB transaction configure + \param[in] udev: pointer to USB device instance + \param[in] buf: transfer data buffer + \param[in] len: transfer data length + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_transc_config (usb_transc *transc, uint8_t *buf, uint16_t len, uint16_t count) +{ + transc->xfer_buf = buf; + transc->xfer_len = len; + transc->xfer_count = count; +} + +/* function declarations */ +/* process USB SETUP transaction */ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num); +/* process USB OUT transaction */ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num); +/* process USB IN transaction */ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num); + +#endif /* __USB_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c new file mode 100644 index 0000000000..0f76ccb9ab --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c @@ -0,0 +1,129 @@ +/*! + \file usbd_core.c + \brief USB device driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_transc.h" +#include "usbd_lld_core.h" + +usbd_int_cb_struct *usbd_int_fops = NULL; + +/*! + \brief configure USB device initialization + \param[in] udev: pointer to USB core instance + \param[in] core: endpoint address + \param[in] usbc: USB class + \param[in] usbha: USB handler + \param[out] none + \retval none +*/ +void usbd_init (usb_dev *udev, usb_desc *desc, usb_class *usbc) +{ + /* configure USBD core basic attributes */ + usbd_core.basic.max_ep_count = 8U; + usbd_core.basic.twin_buf = 1U; + usbd_core.basic.ram_size = 512U; + + usbd_core.dev = udev; + + udev->desc = desc; + udev->class_core = usbc; + udev->drv_handler = &usbd_drv_handler; + + udev->ep_transc[0][TRANSC_SETUP] = _usb_setup_transc; + udev->ep_transc[0][TRANSC_OUT] = _usb_out0_transc; + udev->ep_transc[0][TRANSC_IN] = _usb_in0_transc; + + /* configure power management */ + udev->pm.power_mode = (udev->desc->config_desc[7] & 0x40U) >> 5; + + /* enable USB suspend */ + udev->pm.suspend_enabled = 1U; + + /* USB low level initialization */ + udev->drv_handler->init(); + + /* create serial string */ + serial_string_get((uint16_t *)udev->desc->strings[STR_IDX_SERIAL]); +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + /* configure the transaction level parameters */ + usb_transc *transc = &udev->transc_out[EP_ID(ep_addr)]; + + usb_transc_config(transc, pbuf, buf_len, 0U); + + /* enable endpoint to receive */ + udev->drv_handler->ep_rx_enable(udev, ep_addr); +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + uint8_t ep_num = EP_ID(ep_addr); + + usb_transc *transc = &udev->transc_in[ep_num]; + + uint16_t len = USB_MIN(buf_len, transc->max_len); + + /* configure the transaction level parameters */ + + udev->drv_handler->ep_write(pbuf, ep_num, len); + + usb_transc_config(transc, pbuf + len, buf_len - len, len); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c new file mode 100644 index 0000000000..75bb3c2886 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c @@ -0,0 +1,743 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* USB enumeration handle functions */ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); + +/* standard device request handler */ +static usb_reqsta (*_std_dev_req[]) (usb_dev *udev, usb_req *req) = { + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_dev *udev, uint8_t index, uint16_t *len) = { + [USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req) +{ + /* call device request handle function */ + return (*_std_dev_req[req->bRequest]) (udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->class_core->req_process(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user */ + + return REQ_NOTSUPP; +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation */ + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->dev_desc[0]; + + return udev->desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->config_desc[2]; + + return udev->desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + if (NULL != udev->desc->bos_desc) { + (void)index; + + *len = (uint16_t)udev->desc->bos_desc[2] | (uint16_t)((uint16_t)udev->desc->bos_desc[3] << 8); + + return udev->desc->bos_desc; + } else { + *len = 0U; + + return NULL; + } +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval string descriptor +*/ +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + uint8_t* desc = udev->desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + + usb_reqsta req_status = REQ_NOTSUPP; + + static uint8_t status[2] = {0U}; + + switch(req->bmRequestType & USB_RECPTYPE_MASK) { + /* handle device get status request */ + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + if (udev->pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->pm.remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + break; + + default: + break; + } + break; + /* handle interface get status request */ + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (recp < USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + /* handle endpoint get status request */ + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->transc_out[recp].ep_stall; + } + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], status, 2U, 2U); + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 0U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_clear_stall(udev, ep); + + udev->class_core->req_process(udev, req); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* set endpoint halt feature */ + if (((uint8_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_stall(udev, ep); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->cur_status != (uint8_t)USBD_CONFIGURED) { + if (udev->dev_addr) { + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->transc_in[0]; + + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + if (64U == req->wLength) { + transc->xfer_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + break; + + case USB_DESCTYPE_STR: + if (desc_index < STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, &transc->xfer_len); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->class_core->req_process(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((transc->xfer_len) && (req->wLength)) { + transc->xfer_len = USB_MIN(transc->xfer_len, req->wLength); + + if ((transc->xfer_len < udev->control.req.wLength) && + (0U == transc->xfer_len % transc->max_len)) { + udev->control.ctl_zlp = 1U; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (0U == udev->config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->config) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], &(udev->config), 1U, 1U); + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->class_core->init(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_CONFIGURED; + } + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (0U == config) { + (void)udev->class_core->deinit(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->config) { + /* clear old configuration */ + (void)udev->class_core->deinit(udev, udev->config); + + /* set new configuration */ + udev->config = config; + + (void)udev->class_core->init(udev, config); + } else { + /* no operation */ + } + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + usb_transc_config(&udev->transc_in[0], &(udev->class_core->req_altset), 1U, 1U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + udev->class_core->req_altset = (uint8_t)req->wValue; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: Hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index = 0U; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] none + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if (6U != (unicode_str[0] & 0x00FFU)) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if (0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c new file mode 100644 index 0000000000..952a125352 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c @@ -0,0 +1,60 @@ +/*! + \file usbd_pwr.c + \brief USB device power management driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_pwr.h" + +/*! + \brief start to remote wakeup + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +void usbd_remote_wakeup_active(usb_dev *udev) +{ + resume_mcu(udev); + +#ifdef LPM_ENABLED + if(1 == udev->lpm.L1_remote_wakeup){ + udev->drv_handler->resume(udev); + + udev->lpm.L1_resume = 1U; + } +#endif /* LPM_ENABLED */ + + if(1U == udev->pm.remote_wakeup){ + udev->pm.remote_wakeup_on = 1U; + udev->pm.esof_count = 15U; + udev->drv_handler->resume(udev); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c new file mode 100644 index 0000000000..bbbfe5f5a7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c @@ -0,0 +1,207 @@ +/*! + \file usbd_transc.c + \brief USBD transaction function + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static inline void usb_stall_transc (usb_dev *udev); +static inline void usb_ctl_status_in (usb_dev *udev); +static inline void usb_ctl_data_in (usb_dev *udev); +static inline void usb_ctl_out (usb_dev *udev); +static inline void usb_0len_packet_send (usb_dev *udev); + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + usb_reqsta reqstat = REQ_NOTSUPP; + + uint16_t count = udev->drv_handler->ep_read((uint8_t *)(&udev->control.req), 0U, (uint8_t)EP_BUF_SNG); + + if (count != USB_SETUP_PACKET_LEN) { + usb_stall_transc(udev); + + return; + } + + switch (udev->control.req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request(udev, &udev->control.req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request(udev, &udev->control.req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request(udev, &udev->control.req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == udev->control.req.wLength) { + /* USB control transfer status in stage */ + usb_ctl_status_in(udev); + } else { + if (udev->control.req.bmRequestType & 0x80U) { + usb_ctl_data_in(udev); + } else { + /* USB control transfer data out stage */ + usb_ctl_out(udev); + } + } + } else { + usb_stall_transc(udev); + } +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num) +{ + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_out != NULL)) { + /* device class handle */ + (void)udev->class_core->ctlx_out(udev); + } + + usb_transc_config(&udev->transc_out[ep_num], NULL, 0U, 0U); + + /* enter the control transaction status in stage */ + usb_ctl_status_in(udev); +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + if (udev->control.ctl_zlp) { + /* send 0 length packet */ + usb_0len_packet_send(udev); + + udev->control.ctl_zlp = 0U; + } + + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_in != NULL)) { + (void)udev->class_core->ctlx_in(udev); + } + + /* USB control transfer status out stage */ + usb_ctl_out(udev); + + if (0U != udev->dev_addr) { + udev->drv_handler->set_addr(udev); + + udev->dev_addr = 0U; + } +} + +/*! + \brief USB stalled transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_stall_transc (usb_dev *udev) +{ + usbd_ep_stall(udev, 0x0U); +} + +/*! + \brief USB control transaction status in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_status_in (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} + +/*! + \brief USB control transaction data in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_data_in (usb_dev *udev) +{ + usbd_ep_send(udev, 0U, udev->transc_in[0].xfer_buf, udev->transc_in[0].xfer_len); +} + +/*! + \brief USB control transaction data out & status out stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_out (usb_dev *udev) +{ + udev->drv_handler->ep_rx_enable(udev, 0U); +} + +/*! + \brief USB send 0 length data packet + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_0len_packet_send (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h new file mode 100644 index 0000000000..77862453db --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h @@ -0,0 +1,73 @@ +/*! + \file usbd_lld_core.h + \brief USB device low level driver core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_CORE_H +#define __USBD_LLD_CORE_H + +#include "usbd_lld_regs.h" +#include "usbd_core.h" + +/* double buffer endpoint direction enumeration */ +enum dbuf_ep_dir +{ + DBUF_EP_IN, /*!< double buffer in direction */ + DBUF_EP_OUT, /*!< double buffer out direction */ + DBUF_EP_ERR, /*!< double buffer error direction */ +}; + +/* USBD endpoint ram struct */ +typedef struct +{ + __IO uint32_t tx_addr; /*!< transmission address */ + __IO uint32_t tx_count; /*!< transmission count */ + __IO uint32_t rx_addr; /*!< reception address */ + __IO uint32_t rx_count; /*!< reception count */ +} usbd_ep_ram; + +extern struct _usb_handler usbd_drv_handler; + +/* USB core driver struct */ +typedef struct +{ + usb_basic basic; + usb_dev *dev; +} usb_core_drv; + +extern usb_core_drv usbd_core; + +/* function declarations */ +/* free buffer used from application by toggling the SW_BUF byte */ +void user_buffer_free (uint8_t ep_num, uint8_t dir); + +#endif /* __USBD_LLD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h new file mode 100644 index 0000000000..86ebff830b --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h @@ -0,0 +1,48 @@ +/*! + \file usbd_lld_int.h + \brief USB device low level interrupt handler + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_INT_H +#define __USBD_LLD_INT_H + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_pwr.h" + +/* function declarations */ +/* USB device interrupt service routine */ +void usbd_isr (void); +/* handle USB high priority successful transfer event */ +void usbd_int_hpst (usb_dev *udev); + +#endif /* __USBD_LLD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h new file mode 100644 index 0000000000..52ab730523 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h @@ -0,0 +1,227 @@ +/*! + \file usbd_lld_regs.h + \brief USB device low level registers + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_REGS_H +#define __USBD_LLD_REGS_H + +#include "usbd_conf.h" + +/* USB device registers base address */ +#define USBD USBD_BASE +#define USBD_RAM USBD_RAM_BASE + +/* registers definitions */ +/* common registers */ +#define USBD_CTL (REG32(USBD + 0x40U)) /*!< control register */ +#define USBD_INTF (REG32(USBD + 0x44U)) /*!< interrupt flag register */ +#define USBD_STAT (REG32(USBD + 0x48U)) /*!< status register */ +#define USBD_DADDR (REG32(USBD + 0x4CU)) /*!< device address register */ +#define USBD_BADDR (REG32(USBD + 0x50U)) /*!< buffer address register */ +#define USBD_LPMCS (REG32(USBD + 0x54U)) /*!< USBD LPM control and status register */ + +/* endpoint control and status register */ +#define USBD_EPxCS(ep_num) (REG32(USBD + (ep_num) * 4U)) /*!< endpoint x control and status register address */ + +/* bits definitions */ +/* USBD_CTL */ +#define CTL_STIE BIT(15) /*!< successful transfer interrupt enable mask */ +#define CTL_PMOUIE BIT(14) /*!< packet memory overrun/underrun interrupt enable mask */ +#define CTL_ERRIE BIT(13) /*!< error interrupt enable mask */ +#define CTL_WKUPIE BIT(12) /*!< wakeup interrupt enable mask */ +#define CTL_SPSIE BIT(11) /*!< suspend state interrupt enable mask */ +#define CTL_RSTIE BIT(10) /*!< reset interrupt enable mask */ +#define CTL_SOFIE BIT(9) /*!< start of frame interrupt enable mask */ +#define CTL_ESOFIE BIT(8) /*!< expected start of frame interrupt enable mask */ +#define CTL_L1REQIE BIT(7) /*!< LPM L1 state request interrupt enable */ +#define CTL_L1RSREQ BIT(5) /*!< LPM L1 resume request */ +#define CTL_RSREQ BIT(4) /*!< resume request */ +#define CTL_SETSPS BIT(3) /*!< set suspend state */ +#define CTL_LOWM BIT(2) /*!< low-power mode at suspend state */ +#define CTL_CLOSE BIT(1) /*!< goes to close state */ +#define CTL_SETRST BIT(0) /*!< set USB reset */ + +#ifdef LPM_ENABLED +#define USBD_INTEN BITS(7, 15) /*!< USBD interrupt enable bits */ +#else +#define USBD_INTEN BITS(8, 15) /*!< USBD interrupt enable bits */ +#endif +/* USBD_INTF */ +#define INTF_STIF BIT(15) /*!< successful transfer interrupt flag (read only bit) */ +#define INTF_PMOUIF BIT(14) /*!< packet memory overrun/underrun interrupt flag (clear-only bit) */ +#define INTF_ERRIF BIT(13) /*!< error interrupt flag (clear-only bit) */ +#define INTF_WKUPIF BIT(12) /*!< wakeup interrupt flag (clear-only bit) */ +#define INTF_SPSIF BIT(11) /*!< suspend state interrupt flag (clear-only bit) */ +#define INTF_RSTIF BIT(10) /*!< reset interrupt flag (clear-only bit) */ +#define INTF_SOFIF BIT(9) /*!< start of frame interrupt flag (clear-only bit) */ +#define INTF_ESOFIF BIT(8) /*!< expected start of frame interrupt flag(clear-only bit) */ +#define INTF_L1REQ BIT(7) /*!< LPM L1 transaction is successfully received and acknowledged */ +#define INTF_DIR BIT(4) /*!< direction of transaction (read-only bit) */ +#define INTF_EPNUM BITS(0, 3) /*!< endpoint number (read-only bit) */ + +/* USBD_STAT */ +#define STAT_RXDP BIT(15) /*!< data plus line status */ +#define STAT_RXDM BIT(14) /*!< data minus line status */ +#define STAT_LOCK BIT(13) /*!< locked the USB */ +#define STAT_SOFLN BITS(11, 12) /*!< SOF lost number */ +#define STAT_FCNT BITS(0, 10) /*!< frame number count */ + +/* USBD_DADDR */ +#define DADDR_USBEN BIT(7) /*!< USB module enable */ +#define DADDR_USBADDR BITS(0, 6) /*!< USB device address */ + +/* USBD_EPxCS */ +#define EPxCS_RX_ST BIT(15) /*!< endpoint reception successful transferred */ +#define EPxCS_RX_DTG BIT(14) /*!< endpoint reception data PID toggle */ +#define EPxCS_RX_STA BITS(12, 13) /*!< endpoint reception status bits */ +#define EPxCS_SETUP BIT(11) /*!< endpoint setup transaction completed */ +#define EPxCS_CTL BITS(9, 10) /*!< endpoint type control */ +#define EPxCS_KCTL BIT(8) /*!< endpoint kind control */ +#define EPxCS_TX_ST BIT(7) /*!< endpoint transmission successful transfer */ +#define EPxCS_TX_DTG BIT(6) /*!< endpoint transmission data toggle */ +#define EPxCS_TX_STA BITS(4, 5) /*!< endpoint transmission transfers status bits */ +#define EPxCS_AR BITS(0, 3) /*!< endpoint address */ + +/* USBD_LPMCS */ +#define LPMCS_BLSTAT BITS(4, 7) /*!< bLinkState value */ +#define LPMCS_REMWK BIT(3) /*!< bRemoteWake value */ +#define LPMCS_LPMACK BIT(1) /*!< LPM token acknowledge enable */ +#define LPMCS_LPMEN BIT(0) /*!< LPM support enable */ + +/* constants definitions */ +/* endpoint control and status register mask (no toggle fields) */ +#define EPCS_MASK (EPxCS_RX_ST | EPxCS_SETUP | \ + EPxCS_CTL | EPxCS_KCTL | EPxCS_TX_ST | EPxCS_AR) + +/* EPxCS_CTL[1:0] endpoint type control */ +#define ENDP_TYPE(regval) (EPxCS_CTL & ((regval) << 9U)) + +#define EP_BULK ENDP_TYPE(0U) /* bulk transfers */ +#define EP_CONTROL ENDP_TYPE(1U) /* control transfers */ +#define EP_ISO ENDP_TYPE(2U) /* isochronous transfers */ +#define EP_INTERRUPT ENDP_TYPE(3U) /* interrupt transfers */ +#define EP_CTL_MASK (~EPxCS_CTL & EPCS_MASK) + +/* endpoint kind control mask */ +#define EPKCTL_MASK (~EPxCS_KCTL & EPCS_MASK) + +/* EPxCS_TX_STA[1:0] status for Tx transfer */ +#define ENDP_TXSTAT(regval) (EPxCS_TX_STA & ((regval) << 4U)) + +#define EPTX_DISABLED ENDP_TXSTAT(0U) /* transmission state is disabled */ +#define EPTX_STALL ENDP_TXSTAT(1U) /* transmission state is STALL */ +#define EPTX_NAK ENDP_TXSTAT(2U) /* transmission state is NAK */ +#define EPTX_VALID ENDP_TXSTAT(3U) /* transmission state is enabled */ +#define EPTX_DTGMASK (EPxCS_TX_STA | EPCS_MASK) + +/* EPxCS_RX_STA[1:0] status for Rx transfer */ +#define ENDP_RXSTAT(regval) (EPxCS_RX_STA & ((regval) << 12U)) + +#define EPRX_DISABLED ENDP_RXSTAT(0U) /* reception state is disabled */ +#define EPRX_STALL ENDP_RXSTAT(1U) /* reception state is STALL */ +#define EPRX_NAK ENDP_RXSTAT(2U) /* reception state is NAK */ +#define EPRX_VALID ENDP_RXSTAT(3U) /* reception state is enabled */ +#define EPRX_DTGMASK (EPxCS_RX_STA | EPCS_MASK) + +/* endpoint receive/transmission counter register bit definitions */ +#define EPRCNT_BLKSIZ BIT(15) /* reception data block size */ +#define EPRCNT_BLKNUM BITS(10, 14) /* reception data block number */ +#define EPRCNT_CNT BITS(0, 9) /* reception data count */ + +#define EPTCNT_CNT BITS(0, 9) /* transmisson data count */ + +/* interrupt flag clear bits */ +#define CLR(x) (USBD_INTF = ~INTF_##x) + +/* endpoint receive/transmission counter register bit offset */ +#define BLKSIZE_OFFSET (0x01U) +#define BLKNUM_OFFSET (0x05U) +#define RXCNT_OFFSET (0x0AU) + +#define TXCNT_OFFSET (0x0AU) + +#define BLKSIZE32_MASK (0x1fU) +#define BLKSIZE2_MASK (0x01U) + +#define BLKSIZE32_OFFSETMASK (0x05U) +#define BLKSIZE2_OFFSETMASK (0x01U) + +/* USBD operation macros */ + +/* Tx or Rx transfer status setting (bits EPTX_STA[1:0]) */ + +#define USBD_EP_TX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPTX_DTGMASK) ^ (stat); \ +} while(0) + +#define USBD_EP_RX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPRX_DTGMASK) ^ (stat); \ +} while(0) + +/* clear bit EPxCS_RX_ST/EPxCS_TX_ST in the endpoint control and status register */ + +#define USBD_EP_TX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_TX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +#define USBD_EP_RX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_RX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +/* toggle EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_TX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +#define USBD_RX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_RX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +/* clear EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_TX_DTG) != 0U) {\ + USBD_TX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_RX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_RX_DTG) != 0U) {\ + USBD_RX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_EP_DBL_BUF_SET(ep) (USBD_EPxCS(ep) = (USBD_EPxCS(ep) | EPxCS_KCTL) & EPCS_MASK) + +#endif /* __USBD_LLD_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c new file mode 100644 index 0000000000..28e659c19c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c @@ -0,0 +1,641 @@ +/*! + \file usbd_lld_core.c + \brief USB device low level driver core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_core.h" +#include "usbd_enum.h" + +#define USB_EPTYPE_MASK 0x03U + +#if defined (__CC_ARM) /* ARM Compiler */ +static usbd_ep_ram btable_ep[EP_COUNT]__attribute__((at(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)))); +#elif defined (__ICCARM__) /* IAR Compiler */ + __no_init usbd_ep_ram btable_ep[EP_COUNT] @(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#elif defined (__GNUC__) /* GNU GCC Compiler */ + usbd_ep_ram *btable_ep = (usbd_ep_ram *)(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#endif + +usb_core_drv usbd_core; + +static const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = EP_CONTROL, + [USB_EP_ATTR_BULK] = EP_BULK, + [USB_EP_ATTR_INT] = EP_INTERRUPT, + [USB_EP_ATTR_ISO] = EP_ISO +}; + +/* local function prototypes ('static') */ +static void usbd_dp_pullup (FlagStatus status); +static void usbd_core_reset (void); +static void usbd_core_stop (void); +static void usbd_address_set (usb_dev *udev); +static void usbd_ep_reset (usb_dev *udev); +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes); +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind); +static void usbd_resume (usb_dev *udev); +static void usbd_suspend (void); +static void usbd_leave_suspend (void); +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr); + +struct _usb_handler usbd_drv_handler = { + .dp_pullup = usbd_dp_pullup, + .init = usbd_core_reset, + .deinit = usbd_core_stop, + .suspend = usbd_suspend, + .suspend_leave = usbd_leave_suspend, + .resume = usbd_resume, + .set_addr = usbd_address_set, + .ep_reset = usbd_ep_reset, + .ep_disable = usbd_ep_disable, + .ep_setup = usbd_ep_setup, + .ep_rx_enable = usbd_ep_rx_enable, + .ep_write = usbd_ep_data_write, + .ep_read = usbd_ep_data_read, + .ep_stall_set = usbd_ep_stall_set, + .ep_stall_clear = usbd_ep_stall_clear, + .ep_status_get = usbd_ep_status +}; + +/*! + \brief free buffer used from application by toggling the SW_BUF byte + \param[in] ep_num: endpoint identifier (0..7) + \param[in] dir: endpoint direction which can be OUT(0) or IN(1) + \param[out] none + \retval None +*/ +void user_buffer_free (uint8_t ep_num, uint8_t dir) +{ + if ((uint8_t)DBUF_EP_OUT == dir) { + USBD_TX_DTG_TOGGLE(ep_num); + } else if ((uint8_t)DBUF_EP_IN == dir) { + USBD_RX_DTG_TOGGLE(ep_num); + } else { + /* no operation */ + } +} + +/*! + \brief set the status of pull-up pin + \param[in] status: SET or RESET + \param[out] none + \retval none +*/ +static void usbd_dp_pullup (FlagStatus status) +{ + if (SET == status) { + gpio_bit_set(USB_PULLUP, USB_PULLUP_PIN); + } else { + gpio_bit_reset(USB_PULLUP, USB_PULLUP_PIN); + } +} + +/*! + \brief device core register initialization + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_reset (void) +{ + /* reset the CLOSE bit */ + USBD_CTL = CTL_SETRST; + + /* may be need wait some time(tSTARTUP) */ + + /* clear SETRST bit in USBD_CTL register */ + USBD_CTL = 0U; + + /* clear all pending interrupts */ + USBD_INTF = 0U; + + /* set descriptors table offset in USB dedicated SRAM */ + USBD_BADDR = BTABLE_OFFSET & 0xFFF8U; + +#ifdef LPM_ENABLED + /* enable L1REQ interrupt */ + USBD_CTL = CTL_L1REQIE; + + USBD_LPMCS = LPMCS_LPMACK | LPMCS_LPMEN; +#endif /* LPM_ENABLED */ + + /* enable all interrupts mask bits */ + USBD_CTL |= CTL_STIE | CTL_WKUPIE | CTL_SPSIE | CTL_SOFIE | CTL_ESOFIE | CTL_RSTIE; +} + +/*! + \brief device core register configure when stop device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_stop (void) +{ + /* disable all interrupts and set USB reset */ + USBD_CTL = CTL_SETRST; + + /* clear all interrupt flags */ + USBD_INTF = 0U; + + /* close device */ + USBD_CTL = CTL_SETRST | CTL_CLOSE; +} + +/*! + \brief set device address + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_address_set (usb_dev *udev) +{ + USBD_DADDR = DADDR_USBEN | udev->dev_addr; +} + +/*! + \brief handle USB reset event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_ep_reset (usb_dev *udev) +{ + uint8_t i = 0U; + + usb_transc *transc = &udev->transc_in[0]; + + btable_ep[0].tx_addr = EP0_TX_ADDR; + btable_ep[0].tx_count = 0U; + + transc->max_len = USBD_EP0_MAX_SIZE; + + transc = &udev->transc_out[0]; + + btable_ep[0].rx_addr = EP0_RX_ADDR; + + transc->max_len = USBD_EP0_MAX_SIZE; + + if (transc->max_len > 62U) { + btable_ep[0].rx_count = ((uint16_t)((uint16_t)transc->max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[0].rx_count = ((transc->max_len + 1U) & ~1U) << 9U; + } + + /* reset non-control endpoints */ + for (i = 1U; i < EP_COUNT; i++) { + USBD_EPxCS(i) = (USBD_EPxCS(i) & EPCS_MASK) | i; + } + + /* clear endpoint 0 register */ + USBD_EPxCS(0U)= (uint16_t)(USBD_EPxCS(0U)); + + USBD_EPxCS(0U) = EP_CONTROL | EPRX_VALID | EPTX_NAK; + + /* set device address as default address 0 */ + USBD_DADDR = DADDR_USBEN; + + udev->cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: endpoint buffer address + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = EP_ID(ep_addr); + uint16_t max_len = ep_desc->wMaxPacketSize; + + usb_transc *transc = NULL; + + /* set the endpoint type */ + USBD_EPxCS(ep_num) = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK] | ep_num; + + if (EP_DIR(ep_addr)) { + transc = &udev->transc_in[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].tx_addr = buf_addr; + + /* configure the endpoint status as NAK status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } else { + /* error operation */ + } + } else { + transc = &udev->transc_out[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].rx_addr = buf_addr; + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + USBD_TX_DTG_TOGGLE(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + if (max_len > 62U) { + btable_ep[ep_num].tx_count = (((uint32_t)max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].tx_count = ((max_len + 1U) & ~1U) << 9U; + } + } else { + /* error operation */ + } + + if (max_len > 62U) { + btable_ep[ep_num].rx_count = (((uint32_t)max_len << 5U) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].rx_count = ((max_len + 1U) & ~1U) << 9U; + } + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + /* configure the endpoint status as NAK status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else { + /* error operation */ + } + } +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + USBD_TX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_DISABLED); + } else { + USBD_RX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } +} + +/*! + \brief enable endpoint to receive + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + /* enable endpoint to receive */ + USBD_EP_RX_STAT_SET(EP_ID(ep_addr), EPRX_VALID); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (0U == ep_num) { + USBD_EP_TX_STAT_SET(0U, EPTX_STALL); + USBD_EP_RX_STAT_SET(0U, EPRX_STALL); + } else { + if (EP_DIR(ep_addr)) { + udev->transc_in[ep_num].ep_stall = 1U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_STALL); + } else { + udev->transc_out[ep_num].ep_stall = 1U; + + USBD_EP_RX_STAT_SET(ep_num, EPRX_STALL); + } + } +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + /* clear endpoint data toggle bit */ + USBD_TX_DTG_CLEAR(ep_num); + + udev->transc_in[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + } else { + /* clear endpoint data toggle bit */ + USBD_RX_DTG_CLEAR(ep_num); + + udev->transc_out[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_VALID); + } +} + +/*! + \brief get the endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval endpoint status +*/ +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint32_t epcs = USBD_EPxCS(EP_ID(ep_addr)); + + if (EP_DIR(ep_addr)) { + return (uint8_t)(epcs & EPxCS_TX_STA); + } else { + return (uint8_t)(epcs & EPxCS_RX_STA); + } +} + +/*! + \brief write data from user FIFO to USB RAM + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] bytes: the bytes count of the write data + \param[out] none + \retval none +*/ +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes) +{ + if (0U != bytes) { + uint32_t n; + uint32_t *write_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *write_addr++ = *((uint16_t*)user_fifo); + user_fifo += 2U; + } + } + + btable_ep[ep_num].tx_count = bytes; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); +} + +/*! + \brief read data from USBRAM to user FIFO + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] buf_kind: endpoint buffer kind + \param[out] none + \retval none +*/ +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind) +{ + uint16_t n = 0U, bytes = 0U; + uint32_t *read_addr = NULL; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + if (USBD_EPxCS(ep_num) & EPxCS_TX_DTG) { + bytes = (uint16_t)(btable_ep[ep_num].tx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + } else { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } + } else { + return 0U; + } + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *((uint16_t*)user_fifo) = (uint16_t)*read_addr++; + user_fifo += 2U; + } + + return bytes; +} + +#ifdef USBD_LOWPWR_MODE_ENABLE + +/*! + \brief restore system clocks and power while exiting from suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void lowpower_mode_exit (void) +{ + /* restore system clock */ + +#ifdef LPM_ENABLED + /* enable IRC8M */ + rcu_osci_on(RCU_IRC8M); + + /* wait till IRC8M is ready */ + while (RESET == rcu_flag_get(RCU_FLAG_IRC8MSTB)) { + } +#else + /* enable HXTAL */ + rcu_osci_on(RCU_HXTAL); + + /* wait till HXTAL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_HXTALSTB)) { + } +#endif + + /* enable PLL */ + rcu_osci_on(RCU_PLL_CK); + + /* wait till PLL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_PLLSTB)) { + } + + /* select PLL as system clock source */ + rcu_system_clock_source_config(RCU_CKSYSSRC_PLL); + + /* wait till PLL is used as system clock source */ + while(0x08U != rcu_system_clock_source_get()) { + } + + /* low power sleep on exit disabled */ + system_lowpower_reset(SCB_LPM_DEEPSLEEP); + +#ifdef USE_IRC48M + /* enable IRC48M clock */ + rcu_osci_on(RCU_IRC48M); + + /* wait till IRC48M is ready */ + while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) { + } + + rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M); +#endif +} + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + +/*! + \brief resume the USB device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_resume (usb_dev *udev) +{ +#ifdef LPM_ENABLED + if(1 == udev->lpm.L1_remote_wakeup){ + USBD_CTL |= CTL_L1RSREQ; + } +#endif /* LPM_ENABLED */ + + if(1U == usbd_core.dev->pm.remote_wakeup){ + /* make USB resume */ + USBD_CTL |= CTL_RSREQ; + } +} + +/*! + \brief set USB device to leave mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_leave_suspend (void) +{ + /* clear low_power mode bit in USBD_CTL */ + USBD_CTL &= ~CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* restore normal operations */ + lowpower_mode_exit(); + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + + /* clear SETSPS bit */ + USBD_CTL &= ~CTL_SETSPS; +} + +/*! + \brief set USB device to enter suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_suspend (void) +{ + /* set USB module to suspend and low-power mode */ + USBD_CTL |= CTL_SETSPS | CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* check wakeup flag is set */ + if (0U == (USBD_INTF & INTF_WKUPIF)) { + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } else { + /* clear wakeup interrupt flag */ + CLR(WKUPIF); + + /* clear set_suspend flag */ + USBD_CTL &= ~CTL_SETSPS; + } + +#endif /* USBD_LOWPWR_MODE_ENABLE */ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c new file mode 100644 index 0000000000..c57b282887 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c @@ -0,0 +1,276 @@ + /*! + \file usbd_lld_int.c + \brief USB device low level interrupt routines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_int.h" +#include "usbd_lld_core.h" + +/* local function prototypes ('static') */ +static void usbd_int_suspend (usb_dev *udev); + +/*! + \brief handle USB high priority successful transfer event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_int_hpst (usb_dev *udev) +{ + __IO uint16_t int_status = 0U; + + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + uint8_t transc_num = (uint8_t)TRANSC_UNKNOWN; + + if (int_status & INTF_DIR) { + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + uint16_t count = 0U; + + usb_transc *transc = &udev->transc_out[ep_num]; + + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_DBL); + + user_buffer_free(ep_num, (uint8_t)DBUF_EP_OUT); + + transc->xfer_buf += count; + transc->xfer_count += count; + transc->xfer_len -= count; + + if ((0U == transc->xfer_len) || (count < transc->max_len)) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + + transc_num = (uint8_t)TRANSC_OUT; + } + } + } else { + /* handle the in direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + transc_num = (uint8_t)TRANSC_IN; + } + } + + if ((uint8_t)TRANSC_UNKNOWN != transc_num) { + udev->ep_transc[ep_num][transc_num](udev, ep_num); + } + } +} + +/*! + \brief USB interrupt events service routine + \param[in] none + \param[out] none + \retval none +*/ +void usbd_isr (void) +{ + __IO uint16_t int_status = (uint16_t)USBD_INTF; + __IO uint16_t int_flag = (uint16_t)(USBD_INTF & (USBD_CTL & USBD_INTEN)); + + usb_dev *udev = usbd_core.dev; + + if (INTF_STIF & int_flag) { + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + if (int_status & INTF_DIR) { + /* handle the USB OUT direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + if (USBD_EPxCS(ep_num) & EPxCS_SETUP) { + + if (ep_num == 0U) { + udev->ep_transc[ep_num][TRANSC_SETUP](udev, ep_num); + } else { + return; + } + } else { + usb_transc *transc = &udev->transc_out[ep_num]; + + uint16_t count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_SNG); + + transc->xfer_buf += count; + transc->xfer_count += count; + + if ((transc->xfer_count >= transc->xfer_len) || (count < transc->max_len)) { + if (udev->ep_transc[ep_num][TRANSC_OUT]) { + udev->ep_transc[ep_num][TRANSC_OUT](udev, ep_num); + } + } else { + udev->drv_handler->ep_rx_enable(udev, ep_num); + } + } + } + } else { + /* handle the USB IN direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + usb_transc *transc = &udev->transc_in[ep_num]; + + if (transc->xfer_len == 0U) { + if (udev->ep_transc[ep_num][TRANSC_IN]) { + udev->ep_transc[ep_num][TRANSC_IN](udev, ep_num); + } + } else { + usbd_ep_send(udev, ep_num, transc->xfer_buf, transc->xfer_len); + } + } + } + } + } + + if (INTF_WKUPIF & int_flag) { + /* clear wakeup interrupt flag in INTF */ + CLR(WKUPIF); + + /* restore the old cur_status */ + udev->cur_status = udev->backup_status; + +#ifdef LPM_ENABLED + if ((0U == udev->pm.remote_wakeup_on) && (0U == udev->lpm.L1_resume)) { + resume_mcu(udev); + } else if (1U == udev->pm.remote_wakeup_on) { + /* no operation */ + } else { + udev->lpm.L1_resume = 0U; + } + + /* clear L1 remote wakeup flag */ + udev->lpm.L1_remote_wakeup = 0U; +#else + if (0U == udev->pm.remote_wakeup_on) { + resume_mcu(udev); + } +#endif /* LPM_ENABLED */ + } + + if (INTF_SPSIF & int_flag) { + if(!(USBD_CTL & CTL_RSREQ)) { + usbd_int_suspend (udev); + + /* clear of suspend interrupt flag bit must be done after setting of CTLR_SETSPS */ + CLR(SPSIF); + } + } + + if (INTF_SOFIF & int_flag) { + /* clear SOF interrupt flag in INTF */ + CLR(SOFIF); + + /* if necessary, user can add code here */ + if (NULL != usbd_int_fops) { + (void)usbd_int_fops->SOF(udev); + } + } + + if (INTF_ESOFIF & int_flag) { + /* clear ESOF interrupt flag in INTF */ + CLR(ESOFIF); + + /* control resume time by ESOFs */ + if (udev->pm.esof_count > 0U) { + if (0U == --udev->pm.esof_count) { + if (udev->pm.remote_wakeup_on) { + USBD_CTL &= ~CTL_RSREQ; + + udev->pm.remote_wakeup_on = 0U; + } else { + USBD_CTL |= CTL_RSREQ; + + udev->pm.esof_count = 3U; + udev->pm.remote_wakeup_on = 1U; + } + } + } + } + + if (INTF_RSTIF & int_flag) { + /* clear reset interrupt flag in INTF */ + CLR(RSTIF); + + udev->drv_handler->ep_reset(udev); + } + +#ifdef LPM_ENABLED + if (INTF_L1REQ & int_flag) { + /* clear L1 ST bit in LPM INTF */ + USBD_INTF = CLR(L1REQ); + + /* read BESL field from subendpoint0 register which corresponds to HIRD parameter in LPM spec */ + udev->lpm.besl = (USBD_LPMCS & LPMCS_BLSTAT) >> 4; + + /* read BREMOTEWAKE bit from subendpoint0 register which corresponding to bRemoteWake bit in LPM request */ + udev->lpm.L1_remote_wakeup = (USBD_LPMCS & LPMCS_REMWK) >> 3; + + /* process USB device core layer suspend routine */ + usbd_int_suspend(udev); + } +#endif /* LPM_ENABLED */ +} + +/*! + \brief handle USB suspend event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_int_suspend (usb_dev *udev) +{ + /* store the device current status */ + udev->backup_status = udev->cur_status; + + /* set device in suspended state */ + udev->cur_status = (uint8_t)USBD_SUSPENDED; + + /* usb enter in suspend mode and mcu system in low power mode */ + if (udev->pm.suspend_enabled) { + usbd_to_suspend(udev); + } else { + /* if not possible then resume after xx ms */ + udev->pm.esof_count = 3U; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..51d0c0091b --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..30d5fd6893 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..b965c38218 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,809 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_set_intf (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .set_intf = audio_set_intf, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* Volume Minimum Value */ +#define VOL_MAX 100U /* Volume Maximum Value */ +#define VOL_RES 1U /* Volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Tx endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Rx endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle the AUDIO set interface requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_set_intf(usb_dev *udev, usb_req *req) +{ + udev->dev.class_core->alter_set = req->wValue; + + return USBD_OK; +} + +/*! + \brief handles the control transfer OUT callback + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..3682171868 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,229 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..63e63e82d7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check cdc acm is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..38f47dd4d4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,524 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_proc = cdc_acm_req, + .ctlx_out = cdc_ctlx_out, + + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check cdc acm is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if cdc is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize cdc handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command Tx endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + transc = &udev->dev.transc_out[0]; + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + transc = &udev->dev.transc_in[0]; + + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +static uint8_t cdc_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..538be38f77 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocl code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB dfu function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..e0af991ca4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..35a895a52c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,652 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static const usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to usb device instance + \param[out] none + \retval usb device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..1333ca86b7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitializes all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..b7aa7d98dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..cbec412a86 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *pudev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..bc499cadf2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,488 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* Initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* Initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..e78782611f --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,389 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* Initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..20d1e82646 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,87 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send iap report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..330bc0bd40 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,562 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send iap report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize Tx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the iap device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize iap endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the iap class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..ef3f883780 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *pudev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *pudev); +/* de-initialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *pudev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *pudev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *pudev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *pudev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *pudev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..24f24a8ad9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..cc232adda7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..e411a162fc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..6143edb00e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *pudev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *pudev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..7e5550d7da --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *pudev); +static void msc_bbb_data_send (usb_core_driver *pudev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *pudev); + +/*! + \brief initialize the bbb process + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *pudev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* init the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the Rx FIFO */ + usbd_fifo_flush (pudev, MSC_OUT_EP); + + /* flush the Tx FIFO */ + usbd_fifo_flush (pudev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief de-initialize the BBB machine + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *pudev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (pudev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (pudev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (pudev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *pudev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (pudev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (pudev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (pudev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] pudev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *pudev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (pudev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prapare endpoint to receive next command */ + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *pudev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(pudev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (pudev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (pudev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (pudev); + } else { + if (scsi_process_cmd (pudev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (pudev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (pudev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (pudev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] pudev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *pudev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (pudev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(pudev, MSC_OUT_EP); + } + + usbd_ep_stall(pudev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..1f2e93938e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,319 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *pudev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *pudev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *pudev, usb_req *req); +static uint8_t msc_core_in (usb_dev *pudev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *pudev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +__ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] pudev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *pudev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + pudev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC Tx endpoint */ + usbd_ep_setup (pudev, &(msc_config_desc.msc_epin)); + + /* configure MSC Rx endpoint */ + usbd_ep_setup (pudev, &(msc_config_desc.msc_epout)); + + /* init the BBB layer */ + msc_bbb_init(pudev); + + return USBD_OK; +} + +/*! + \brief de-initialize the MSC device + \param[in] pudev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *pudev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (pudev, MSC_IN_EP); + usbd_ep_clear (pudev, MSC_OUT_EP); + + /* un-init the BBB layer */ + msc_bbb_deinit(pudev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] pudev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *pudev, usb_req *req) +{ + usb_transc *transc = &pudev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(pudev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (pudev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *pudev, uint8_t ep_num) +{ + msc_bbb_data_in(pudev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *pudev, uint8_t ep_num) +{ + msc_bbb_data_out (pudev, ep_num); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..56ce9e3eeb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..5d68b810fd --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,724 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_process_read (usb_core_driver *pudev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *pudev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *pudev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *pudev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *pudev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (pudev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (pudev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (pudev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (pudev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (pudev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (pudev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (pudev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (pudev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (pudev, lun, params); + + case SCSI_READ10: + return scsi_read10 (pudev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (pudev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (pudev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (pudev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (pudev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (pudev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (pudev, lun, params); + + default: + scsi_sense_code (pudev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional aense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *pudev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(pudev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + /* Evpd is set */ + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (pudev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (pudev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (pudev, lun); +} + +/*! + \brief process Write10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (pudev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (pudev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (pudev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (pudev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (pudev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (pudev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (pudev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *pudev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (pudev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *pudev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(pudev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (pudev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *pudev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(pudev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (pudev, CSW_CMD_PASSED); + } else { + /* prapare endpoint to receive next packet */ + usbd_ep_recev (pudev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *pudev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..3e32cd603c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor struct */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..6f7ac0de91 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,309 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief de-initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to usb device instance + \param[in] req: device class-specific request + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..cdfdeac1c7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions protype + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..0a2223bde4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..7bc1ac131d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..5ef0a41aaa --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to usb core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..77107d5e7c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..e299d532d3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,264 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..b332de8e99 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,163 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the Tx FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the Rx FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a Tx FIFO or all Tx FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire Rx FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..31cf52d6c9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,300 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device contrl in callback */ + uint8_t (*ctlx_out) (usb_dev *udev); /*!< device contrl out callback */ + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + usb_perp_dev dev; /*!< USB peripheral device */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..0cf18b5bf7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,193 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; + usb_core_regs regs; + usb_host_drv host; +} usb_core_driver; + +/*! + \brief get USB even frame + \param[in] pudev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *pudev) +{ + return (uint8_t)!(pudev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] pudev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock) +{ + pudev->regs.hr->HCTL &= ~HCTL_CLKSEL; + pudev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] pudev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *pudev) +{ + return *pudev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] pudev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *pudev) +{ + return *pudev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] pudev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *pudev) +{ + return (pudev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *pudev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *pudev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *pudev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..34a4b6b24c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,69 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +/* configure the CTC peripheral */ +#ifdef USE_IRC48M + void ctc_config(void); +#endif /* USE_IRC48M */ + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..b07922b2ac --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,657 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/* USB IN endpoint 0 transmit FIFO length register bits definitions */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< Transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< Packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< Embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..0e2803a98d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..995e32e791 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *puhost); + uint8_t (*disconnect) (usbh_host *puhost); + uint8_t (*port_enabled) (usbh_host *puhost); + uint8_t (*port_disabled) (usbh_host *puhost); + uint8_t (*SOF) (usbh_host *puhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *pudev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..7944a8194b --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,343 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to usb capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* init the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the Tx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a Tx FIFO or all Tx FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for Tx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to usb core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for Rx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (fifo == 0U) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* Multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..22be493ad7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,610 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* config periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 0 to 3's Tx FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all Tx FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire Rx FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the Tx FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure usb transaction to start OUT transfer + \param[in] udev: pointer to usb device + \param[in] transc: the usb OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* un-gate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..95eac3758d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,452 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] pudev: pointer to selected usb host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *pudev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *pudev->regs.PWRCLKCTL = 0U; + + /* support FS/LS only */ + pudev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == pudev->bp.core_enum) { + /* set Rx FIFO size */ + pudev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + pudev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set hnp enable in the usb_otg control register */ + pudev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all Tx FIFOs in device or host mode */ + usb_txfifo_flush (&pudev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&pudev->regs); + + /* disable all interrupts */ + pudev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + pudev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + pudev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < pudev->bp.num_pipe; i++) { + pudev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + pudev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (pudev, 1U); +#endif /* USE_OTG_MODE */ + + pudev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == pudev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + pudev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + pudev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] pudev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (pudev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *pudev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] pudev: pointer to usb device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *pudev) +{ + __IO uint32_t port = usb_port_read (pudev); + + *pudev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *pudev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &pudev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + pudev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == pudev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + pudev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + pudev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + pudev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &pudev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + pudev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == pudev->bp.transfer_mode) { + pudev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(pudev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == pudev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + pudev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + pudev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the tx fifo. */ + usb_txfifo_write (&pudev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + pudev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] pudev: pointer to usb device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *pudev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + pudev->regs.hr->HACHINTEN = 0x0U; + pudev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < pudev->bp.num_pipe; i++) { + pp_ctl = pudev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + pudev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&pudev->regs); + usb_txfifo_flush (&pudev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..f378dad4bc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,491 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + udev->dev.cur_status = USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* Session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* Clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the Tx FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..3dc8e37c42 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *pudev); +static uint32_t usbh_int_pipe (usb_core_driver *pudev); +static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] pudev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *pudev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (pudev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&pudev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(pudev->host.data); + + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (pudev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (pudev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (pudev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (pudev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (pudev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(pudev->host.data); + + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + pudev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (pudev, 1U); + + pudev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *pudev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + pudev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(pudev, pp_num); + + pudev->regs.pr[pp_num]->HCHINTF = pp_int; + + pudev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *pudev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *pudev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*pudev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(pudev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*pudev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*pudev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(pudev); + uint32_t clock_type = pudev->regs.hr->HCTL & HCTL_CLKSEL; + + pudev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + pudev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) { + usb_phyclock_config (pudev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + pudev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (pudev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(pudev->host.data); + + pudev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(pudev->host.data); + } + } + + if (port_reset) { + usb_port_reset(pudev); + } + + /* clear port interrupts */ + *pudev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *pudev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < pudev->bp.num_pipe; pp_num++) { + if ((pudev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (pudev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (pudev, pp_num); + } else { + retval |= usbh_int_pipe_out (pudev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] pudev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num) +{ + usb_pr *pp_reg = pudev->regs.pr[pp_num]; + + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the pudev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == pudev->bp.transfer_mode) { + pudev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(pudev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] pudev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num) +{ + usb_pr *pp_reg = pudev->regs.pr[pp_num]; + + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + pudev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (pudev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == pudev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (pudev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + pudev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = pudev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != pudev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + pudev->host.pipe[pp_num].xfer_buf += count; + pudev->host.pipe[pp_num].xfer_count += count; + + pudev->host.backup_xfercount[pp_num] = pudev->host.pipe[pp_num].xfer_count; + + if (pudev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = pudev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + pudev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = pudev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + pudev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] pudev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &pudev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &pudev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(pudev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != pudev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > pudev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)pudev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + pudev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + pudev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((pudev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, pp_num, len); + + pudev->host.pipe[pp_num].xfer_buf += len; + pudev->host.pipe[pp_num].xfer_len -= len; + pudev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..f58463172f --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *pudev, usbh_host *puhost); + void (*machine)(usb_core_driver *pudev, usbh_host *puhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *pudev, + usbh_host *puhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..0d93792ce4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void USR_KEYBRD_Init (void); +/* process keyboard data */ +void USR_KEYBRD_ProcessData (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *pudev, usbh_host *puhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *pudev, usbh_host *puhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *pudev, usbh_host *puhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..94b51654b5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void USR_MOUSE_Init (void); +/* process mouse data */ +void USR_MOUSE_ProcessData (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *pudev, usbh_host *puhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *pudev, usbh_host *puhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *pudev, usbh_host *puhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..45c68af100 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,61 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..be3d9d9132 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..978502f9fc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,675 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *puhost); +static usbh_status usbh_hid_itf_init (usbh_host *puhost); +static usbh_status usbh_hid_class_req (usbh_host *puhost); +static usbh_status usbh_hid_handle (usbh_host *puhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *puhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *puhost); +static usbh_status usbh_hid_desc_get (usbh_host *puhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *puhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *puhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] puhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *puhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (puhost, report_buf, report_len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set report + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *pudev, + usbh_host *puhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (puhost, report_buf, report_len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief de-initialize the host pipes used for the HID class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (puhost->data, hid->pipe_in); + + usbh_pipe_free (puhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (puhost->data, hid->pipe_out); + + usbh_pipe_free (puhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *pudev, usbh_host *puhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == puhost->cur_state) { + interface_protocol = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == puhost->cur_state) || + (HOST_USER_INPUT == puhost->cur_state) || + (HOST_CHECK_CLASS == puhost->cur_state) || + (HOST_CLASS_HANDLER == puhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *puhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&puhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + puhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&puhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check for available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (puhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(puhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (puhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(puhost->data, hid_handler.pipe_out, 0U); + } + } + + puhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (puhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, puhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(puhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (puhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (puhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *puhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(puhost->data, puhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(puhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (puhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (puhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (puhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(puhost->data, puhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (puhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (puhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] puhost: pointer to usb host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *puhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (puhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] puhost: pointer to usb host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *puhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set idle state + \param[in] puhost: pointer to usb host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *puhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] puhost: pointer to usb host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *puhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..b32b8aef7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *pudev, usbh_host *puhost); + +/*! + \brief initialize the keyboard function + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, puhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user init*/ + USR_KEYBRD_Init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] pudev: pointer to USB core instance + \param[in] puhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *pudev, usbh_host *puhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(pudev, puhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *pudev, usbh_host *puhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(pudev, puhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + USR_KEYBRD_ProcessData(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..f684298df9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *pudev, usbh_host *puhost); + +/*! + \brief initialize the mouse function + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, puhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + USR_MOUSE_Init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *pudev, usbh_host *puhost) +{ + if(usbh_hid_mouse_decode(pudev, puhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *pudev, usbh_host *puhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(pudev, puhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + USR_MOUSE_ProcessData(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..04d09567ce --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: Ok) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..75eea727b2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *puhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *puhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *puhost, uint8_t direction); +/* reset msc bot request struct */ +usbh_status usbh_msc_bot_reset (usbh_host *puhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *puhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..914aa44501 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for msc process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *puhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..562adb24cb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *puhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *puhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *puhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *puhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *puhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *puhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *puhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..071a94bfc2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] puhost: pointer to usb host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *puhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *puhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (puhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (puhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (puhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (puhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (puhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (puhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(puhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(puhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (puhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(puhost->data, msc->pipe_out); + usbh_pipe_toggle_set(puhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(puhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(puhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] puhost: pointer to usb host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *puhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeture command on bulk IN endpoint */ + status = usbh_clrfeature(puhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(puhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset msc bot transfer + \param[in] puhost: pointer to usb host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] puhost: pointer to usb host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *puhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (puhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we will return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..53c9c84882 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,561 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *puhost); +static usbh_status usbh_msc_itf_init (usbh_host *puhost); +static usbh_status usbh_msc_req (usbh_host *puhost); +static usbh_status usbh_msc_handle (usbh_host *puhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *puhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *puhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *puhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&puhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + puhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0, sizeof(usbh_msc_handler)); + + puhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&puhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &puhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &puhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(puhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(puhost->data, msc_handler.ep_in); + + usbh_msc_bot_init(puhost); + + /* open the new channels */ + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (puhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (puhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief de-initialize interface by freeing host channels allocated to interface + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *puhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (puhost->data, msc->pipe_out); + usbh_pipe_free (puhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (puhost->data, msc->pipe_in); + usbh_pipe_free (puhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (puhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(puhost, 0x00U, puhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = puhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(puhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(puhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(puhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for recovering error code */ + scsi_status = usbh_msc_request_sense (puhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if (((puhost->control.timer > msc->timer) && ((puhost->control.timer - msc->timer) < 10000U)) \ + || ((puhost->control.timer < msc->timer) && ((puhost->control.timer + 0x3FFFU - msc->timer) < 10000U))){ + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + puhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] puhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *puhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (puhost->control.ctl_state == CTL_IDLE) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (puhost, maxlun, 1U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *puhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(puhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(puhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (puhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *puhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == puhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + usb_core_driver *pudev = (usb_core_driver *)puhost->data; + + if ((0U == pudev->host.connect_status) || + (HOST_CLASS_HANDLER != puhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(puhost, lun, pbuf, address, length); + + timeout = puhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(puhost, lun)) { + if (((puhost->control.timer > timeout) && ((puhost->control.timer - timeout) > (1000U * length))) \ + || ((puhost->control.timer < timeout) && ((puhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == pudev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *pudev = (usb_core_driver *)puhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + if ((0U == pudev->host.connect_status) || + (HOST_CLASS_HANDLER != puhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(puhost, lun, pbuf, address, length); + + timeout = puhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(puhost, lun)) { + if (((puhost->control.timer > timeout) && ((puhost->control.timer - timeout) > (1000U * length))) \ + || ((puhost->control.timer < timeout) && ((puhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == pudev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..4923d3af00 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *pudev = (usb_core_driver *)usb_host.data; + + if (pudev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *pudev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (pudev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!pudev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *pudev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (pudev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!pudev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* Year 2019 */ + | ((DWORD)1U << 21U) /* Month 1 */ + | ((DWORD)1U << 16U) /* Mday 1 */ + | ((DWORD)0U << 11U) /* Hour 0 */ + | ((DWORD)0U << 5U) /* Min 0 */ + | ((DWORD)0U >> 1U); /* Sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..d6f47445d3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,397 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implemention + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *puhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(puhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] puhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *puhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to scsi capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *puhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *puhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *puhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *puhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *puhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..e52da96a1e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,274 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *puhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *pudev, uint8_t pp_num) +{ + return pudev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *pudev, uint8_t pp_num) +{ + return pudev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *puhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *puhost, usbh_class *puclass); +/* de-initialize USB host */ +usbh_status usbh_deinit (usbh_host *puhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *puhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *puhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..2e666fd907 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *puhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *puhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *puhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *puhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *puhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *puhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *puhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..4d899a683a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *pudev, uint8_t pp_num, uint8_t toggle) +{ + if (pudev->host.pipe[pp_num].ep.dir) { + pudev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + pudev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *pudev, uint8_t pp_num) +{ + if (pudev->host.pipe[pp_num].ep.dir) { + return pudev->host.pipe[pp_num].data_toggle_in; + } else { + return pudev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *pudev, + usb_dev_prop *udev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *pudev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *pudev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..8d876c8a2d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *puhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..777942e302 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,650 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *puhost); +static uint8_t usbh_connect (usbh_host *puhost); +static uint8_t usbh_disconnect (usbh_host *puhost); +static uint8_t usbh_port_enabled (usbh_host *puhost); +static uint8_t usbh_port_disabled (usbh_host *puhost); +static usbh_status usbh_enum_task (usbh_host *puhost); + +#ifdef USB_FS_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *pudev); +static void usb_hwp_resume(usb_core_driver *pudev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] puhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *puhost, usbh_user_cb *user_cb) +{ + /* host de-initializations */ + usbh_deinit(puhost); + + puhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)puhost; + puhost->data = (void *)&usbh_core; + + /* upon init call usr call back */ + puhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] puhost: pointer to usb host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *puhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (puhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + puhost->uclass[puhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief de-initialize USB host + \param[in] puhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *puhost) +{ + /* software init */ + puhost->cur_state = HOST_DEFAULT; + puhost->backup_state = HOST_DEFAULT; + puhost->enum_state = ENUM_DEFAULT; + + puhost->control.ctl_state = CTL_IDLE; + puhost->control.max_len = USB_FS_EP0_MAX_LEN; + + puhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + puhost->dev_prop.speed = PORT_SPEED_FULL; + puhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, puhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, puhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *puhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != puhost->cur_state)) { + if (puhost->cur_state != HOST_DEV_DETACHED) { + puhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (puhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + puhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + puhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + puhost->cur_state = HOST_DEV_ATTACHED; + + puhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + puhost->usr_cb->dev_speed_detected(puhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + puhost->usr_cb->dev_attach(); + puhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + puhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &puhost->dev_prop, + puhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)puhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &puhost->dev_prop, + puhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)puhost->control.max_len); + + puhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (puhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + puhost->usr_cb->dev_enumerated(); + +#ifdef USB_FS_LOW_PWR_ENABLE + puhost->cur_state = HOST_SUSPENDED; +#else + puhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((puhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(puhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + puhost->cur_state = HOST_CHECK_CLASS; + } + } else { + puhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (puhost->class_num == 0U) { + puhost->cur_state = HOST_ERROR; + } else { + puhost->active_class = NULL; + + uint8_t itf_class = puhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < puhost->class_num; index++) { + if ((puhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + puhost->active_class = puhost->uclass[index]; + } + } + + if (puhost->active_class != NULL) { + puhost->cur_state = HOST_USER_INPUT; + } else { + puhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == puhost->usr_cb->dev_user_input()) { + if ((USBH_OK == puhost->active_class->class_init(puhost))) { + puhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_FS_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(puhost, FEATURE_SELECTOR_DEV, 0U)) { + puhost->suspend_flag = 1; + usb_hwp_suspend(puhost->data); + puhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + puhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(puhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initalization */ + puhost->usr_cb->dev_init(); + + puhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard contol requests state machine */ + status = puhost->active_class->class_requests(puhost); + + if (USBH_OK == status) { + puhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (puhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = puhost->active_class->class_machine(puhost); + + usbh_error_handler (puhost, status); + break; + + case HOST_ERROR: + /* re-initilaize host for new enumeration */ + usbh_deinit (puhost); + puhost->usr_cb->dev_deinit(); + puhost->active_class->class_deinit(puhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + puhost->usr_cb->dev_detach(); + + /* re-initilaize host for new enumeration */ + usbh_deinit(puhost); + puhost->usr_cb->dev_deinit(); + puhost->active_class->class_deinit(puhost); + usbh_pipe_delete(&usbh_core); + puhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] puhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *puhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + puhost->usr_cb->dev_error(); + + puhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + puhost->cur_state = HOST_ERROR; + + /* user callback for initalization */ + puhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *puhost) +{ + /* this callback could be used to implement a scheduler process */ + puhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (puhost->active_class != NULL) { + if (puhost->active_class->class_sof != NULL) { + puhost->active_class->class_sof(puhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *puhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *puhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *puhost) +{ + usbh_core.host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *puhost) +{ + usbh_core.host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] puhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *puhost) +{ + uint8_t str_buf[64]; + + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (puhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */ + if (USBH_OK == usbh_devdesc_get (puhost, 8U)) { + puhost->control.max_len = puhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + puhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)puhost->control.max_len); + + usbh_pipe_update (&usbh_core, + puhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)puhost->control.max_len); + + puhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (puhost, USB_DEV_DESC_LEN)) { + puhost->usr_cb->dev_devdesc_assigned(&puhost->dev_prop.dev_desc); + + index_mfc_str = puhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = puhost->dev_prop.dev_desc.iProduct; + index_serial_str = puhost->dev_prop.dev_desc.iSerialNumber; + + puhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (puhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + puhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + puhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + puhost->control.pipe_in_num, + puhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + puhost->control.pipe_out_num, + puhost->dev_prop.addr, + 0U, 0U); + + puhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (puhost, USB_CFG_DESC_LEN)) { + puhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full config descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (puhost, puhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + puhost->usr_cb->dev_cfgdesc_assigned (&puhost->dev_prop.cfg_desc_set.cfg_desc, + &puhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &puhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + puhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (puhost, + puhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + puhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (puhost, + puhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + puhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (puhost, + puhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + puhost->usr_cb->dev_seral_str(str_buf); + puhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + puhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (puhost, (uint16_t)puhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + puhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + + +#ifdef USB_FS_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] pudev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *pudev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *pudev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *pudev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(pudev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *pudev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *pudev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] pudev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *pudev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(pudev); + + hprt |= HPCS_PSP; + + *pudev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *pudev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *pudev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..19a71167d0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumeration driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] puhost: pointer to usb host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + puhost->control.buf = buf; + puhost->control.ctl_len = len; + + puhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] puhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *puhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (puhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&puhost->dev_prop.dev_desc, puhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] puhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *puhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = puhost->dev_prop.cfgdesc_rawdata; +#else + pdata = puhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, pdata, len); + } + + status = usbh_ctl_handler (puhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&puhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&puhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] puhost: pointer to usb host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *puhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (puhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (puhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] puhost: pointer to usb host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *puhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] puhost: pointer to usb host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *puhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] puhost: pointer to usb host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *puhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] puhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] puhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] puhost: pointer to usb host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *puhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &puhost->control; + usb_core_driver *pudev = (usb_core_driver *)puhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == pudev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(pudev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to usb device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to usb configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to usb interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to usb endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..ab14434619 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *pudev); + +/*! + \brief create a pipe + \param[in] pudev: pointer to usb core instance + \param[in] udev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *pudev, + usb_dev_prop *udev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->dev_addr = udev->addr; + pp->dev_speed = udev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(udev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (pudev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] pudev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *pudev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (pudev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] pudev: pointer to usb core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (pudev); + + if (HC_ERROR != pp_num) { + pudev->host.pipe[pp_num].in_used = 1U; + pudev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + pudev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] pudev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + pudev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] pudev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *pudev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + pudev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] pudev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *pudev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == pudev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..64201003a2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,370 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *puhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *puhost); +static void usbh_data_in_transc (usbh_host *puhost); +static void usbh_data_out_transc (usbh_host *puhost); +static void usbh_status_in_transc (usbh_host *puhost); +static void usbh_status_out_transc (usbh_host *puhost); +static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] pudev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (pudev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] pudev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (pudev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] pudev: pointer to usb core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* Toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (pudev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] puhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + + switch (puhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (puhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (puhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (puhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (puhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (puhost); + break; + + case CTL_FINISH: + puhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + puhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] puhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *puhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(puhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + puhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + puhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(puhost->data)- puhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + puhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *puhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (puhost->data, + puhost->control.setup.data, + puhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (puhost, puhost->control.pipe_out_num, 0U)) { + uint8_t dir = (puhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (puhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + puhost->control.ctl_state = CTL_DATA_IN; + } else { + puhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + puhost->control.ctl_state = CTL_STATUS_OUT; + } else { + puhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + puhost->control.timer = (uint16_t)usb_curframe_get(puhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *puhost) +{ + usbh_data_recev (puhost->data, + puhost->control.buf, + puhost->control.pipe_in_num, + puhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (puhost, puhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_STATUS_OUT; + + puhost->control.timer = (uint16_t)usb_curframe_get(puhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *puhost) +{ + usbh_pipe_toggle_set(puhost->data, puhost->control.pipe_out_num, 1U); + + usbh_data_send (puhost->data, + puhost->control.buf, + puhost->control.pipe_out_num, + puhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (puhost, puhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_STATUS_IN; + + puhost->control.timer = (uint16_t)usb_curframe_get(puhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *puhost) +{ + uint8_t pp_num = puhost->control.pipe_in_num; + + usbh_data_recev (puhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (puhost, pp_num, NODATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *puhost) +{ + uint8_t pp_num = puhost->control.pipe_out_num; + + usbh_data_send (puhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (puhost, pp_num, NODATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] pudev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num) +{ + pudev->host.pipe[pp_num].urb_state = URB_IDLE; + pudev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (pudev, pp_num); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..f228286740 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..3e70345725 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..4c5d11781e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..ddfbcc8a2d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..21cf610890 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..3dd33165ff --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript new file mode 100644 index 0000000000..09f70ea989 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript @@ -0,0 +1,57 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/GD/GD32F30x/Source/system_gd32f30x.c +GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c +GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c +GD32F30x_standard_peripheral/Source/gd32f30x_exti.c +GD32F30x_standard_peripheral/Source/gd32f30x_misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_enet.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_dac.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_wwdgt.c'] + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c'] + +path = [ + cwd + '/CMSIS/GD/GD32F30x/Include', + cwd + '/CMSIS', + cwd + '/GD32F30x_standard_peripheral/Include',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h new file mode 100644 index 0000000000..e3cd89f728 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h @@ -0,0 +1,1790 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) /* Cosmic */ + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ +#include /* Compiler specific SIMD Intrinsics */ + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000 + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0 + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9 /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8 /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __IO uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IO uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IO uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __I uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __I uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register */ +#define FPU_FPCCR_ASPEN_Pos 31 /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30 /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8 /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6 /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5 /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4 /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3 /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1 /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0 /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL << FPU_FPCCR_LSPACT_Pos) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register */ +#define FPU_FPCAR_ADDRESS_Pos 3 /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register */ +#define FPU_FPDSCR_AHP_Pos 26 /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25 /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24 /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22 /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28 /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24 /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20 /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16 /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12 /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8 /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4 /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0 /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL << FPU_MVFR0_A_SIMD_registers_Pos) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28 /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24 /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4 /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0 /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL << FPU_MVFR1_FtZ_mode_Pos) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ +/* NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); enable interrupt */ + NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h new file mode 100644 index 0000000000..f9bceff1e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h @@ -0,0 +1,697 @@ +/**************************************************************************//** + * @file core_cm4_simd.h + * @brief CMSIS Cortex-M4 SIMD Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifndef __CORE_CM4_SIMD_H +#define __CORE_CM4_SIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/******************************************************************************* + * Hardware Abstraction Layer + ******************************************************************************/ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32) ) >> 32)) + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ +#include + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ +/* not yet supported */ + + +#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/ +/* Cosmic specific functions */ +#include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_SIMD_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmFunc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmFunc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmFunc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmInstr.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmInstr.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmInstr.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..66e224d03a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..b143c5fa44 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..6f686aec70 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,777 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* volume Minimum Value */ +#define VOL_MAX 100U /* volume Maximum Value */ +#define VOL_RES 1U /* volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev audio_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set audio_config_set __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_audio_handler audio_handler __ALIGN_END; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize TX endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + if (AUDIO_OUT_EP == ep_num) { + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } + } else { + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..fbe56d907b --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,228 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..c1a2bc8f80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint8_t packet_sent; + uint8_t packet_receive; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..a950c091c8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,515 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev cdc_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_cdc_desc_config_set cdc_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + + .req_proc = cdc_acm_req, + + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usb_cdc_handler cdc_handler __ALIGN_END; + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command TX endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U == ep_num) { + if (udev->dev.class_core->alter_set != NO_CMD) + { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + } else { + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..e62dd75cf2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..2198eb2376 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..676a8cda78 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,653 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_data_in(usb_dev *udev, uint8_t ep_num); +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev dfu_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_dfu_desc_config_set dfu_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static __ALIGN_BEGIN const usb_desc_str config_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static __ALIGN_BEGIN const usb_desc_str interface_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .data_in = dfu_data_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_dfu_handler dfu_handler __ALIGN_END; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_data_in (usb_dev *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + dfu_getstatus_complete(udev); + } + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..11c161c8f1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..f320f77e40 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..773470d67f --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x29U + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..fd4c9ccca7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,486 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev custom_hid_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_hid_desc_config_set custom_hid_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +__ALIGN_BEGIN const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] __ALIGN_END = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN custom_hid_handler hid_handler __ALIGN_END; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* Initialize the data RX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + if ((CUSTOMHID_OUT_EP & 0x7FU) == ep_num) { + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED1); + } else { + gd_eval_led_off(LED1); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + break; + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; + } + + return USBD_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..8252e33e97 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,384 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev hid_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set hid_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +__ALIGN_BEGIN const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation function structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN standard_hid_handler hid_handler __ALIGN_END; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..a84dc4a255 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,93 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#elif defined(USE_USB_HS) + #define USB_DESC_LEN_IAP_REPORT 36U +#else + #error "please select 'USE_USB_FS' or 'USE_USB_HS'" +#endif + +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..6dced66ab8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,571 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ +#ifdef USE_USB_FS + 0x95, REPORT_OUT_COUNT, +#else + #ifdef USE_ULPI_PHY + 0x96, BYTE_LOW(REPORT_OUT_COUNT), BYTE_HIGH(REPORT_OUT_COUNT), + #elif defined(USE_EMBEDDED_PHY) + 0x95, REPORT_OUT_COUNT, + #endif +#endif + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize TX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize RX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize IAP endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the IAP class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if ((IAP_OUT_EP & 0x7FU) == ep_num) { + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + } + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..266b932d7a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..a67b539746 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..f7a180a326 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..c39778fcf6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..188e592ced --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..d9a74d5d5d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the RX FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the TX FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief de-initialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..9c6e9f0857 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,322 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC TX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC RX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief de-initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + if ((MSC_IN_EP & 0x7FU) == ep_num) { + msc_bbb_data_in(udev, ep_num); + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + if (MSC_OUT_EP == ep_num) { + msc_bbb_data_out (udev, ep_num); + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..53a1afc626 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..7afae6fa30 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,685 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + if (1U == msc->scsi_disk_pop) { + usbd_disconnect (udev); + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..88c933ac94 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..71818f03b9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +__ALIGN_BEGIN uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] __ALIGN_END = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev printer_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_printer_desc_config_set printer_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..8446487b1d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions protype + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..ffa7f0ca93 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFF7A10U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFF7A14U) /* device ID2 */ +#define DEVICE_ID3 (0x1FFF7A18U) /* device ID3 */ + +#define DEVICE_ID (0x40023D00U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..014ea34aee --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..065dd3ad15 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..21094d5df4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..a4349ee3a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c @@ -0,0 +1,264 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->data_out != NULL) { + (void)udev->dev.class_core->data_out (udev, 0U); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->data_in != NULL) { + (void)udev->dev.class_core->data_in (udev, 0U); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..daefca3de5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h @@ -0,0 +1,343 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#ifdef USE_DEVICE_MODE + #include "usbd_conf.h" +#endif /* USE_DEVICE_MODE */ + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +#ifdef USE_DEVICE_MODE + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +#endif /* USE_DEVICE_MODE */ + +#ifdef USE_HOST_MODE + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +#endif /* USE_HOST_MODE */ + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + +#ifdef USE_DEVICE_MODE + usb_perp_dev dev; /*!< USB peripheral device */ +#endif /* USE_DEVICE_MODE */ + +#ifdef USE_HOST_MODE + usb_host_drv host; +#endif /* USE_HOST_MODE */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the TX FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the RX FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a TX FIFO or all TX FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire RX FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..8c0431bc1f --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,197 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..55ac908d52 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h @@ -0,0 +1,123 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..725a8d48b0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,71 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB data line gpio */ +void usb_gpio_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +/* configure the CTC peripheral */ +#ifdef USE_IRC48M + void ctc_config(void); +#endif /* USE_IRC48M */ + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..9620357a5a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,662 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/** + * @brief USB IN endpoint 0 transmit FIFO length register bits definitions + */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..dc4a70cc8d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,52 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#ifdef USB_HS_DEDICATED_EP1_ENABLED +/* USB dedicated IN endpoint 1 interrupt service routine handler */ +uint32_t usbd_int_dedicated_ep1in (usb_core_driver *udev); +/* USB dedicated OUT endpoint 1 interrupt service routine handler */ +uint32_t usbd_int_dedicated_ep1out (usb_core_driver *udev); +#endif /* USB_HS_DEDICATED_EP1_ENABLED */ + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..d42146e46d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*port_enabled) (usbh_host *uhost); + uint8_t (*port_disabled) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..50c1544214 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c @@ -0,0 +1,363 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_HS: + usb_basic->base_reg = (uint32_t)USBHS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBHS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBHS_MAX_EP_COUNT; + +#ifdef USB_ULPI_PHY_ENABLED + usb_basic->phy_itf = USB_ULPI_PHY; +#else + usb_basic->phy_itf = USB_EMBEDDED_PHY; +#endif /* USB_ULPI_PHY_ENABLED */ + +#ifdef USB_HS_INTERNAL_DMA_ENABLED + usb_basic->transfer_mode = USB_USE_DMA; +#endif /* USB_HS_INTERNAL_DMA_ENABLED */ + break; + + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initialize the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the TX FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a TX FIFO or all TX FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for TX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for RX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (fifo == 0U) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..3f6a52a3c4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,664 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +#ifdef USB_HS_CORE + +uint16_t USBHS_TX_FIFO_SIZE[USBHS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_HS_SIZE, + (uint16_t)TX1_FIFO_HS_SIZE, + (uint16_t)TX2_FIFO_HS_SIZE, + (uint16_t)TX3_FIFO_HS_SIZE, + (uint16_t)TX4_FIFO_HS_SIZE, + (uint16_t)TX5_FIFO_HS_SIZE +}; + +#endif /* USBHS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 0 to 3's TX FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + +#ifdef USB_HS_CORE + if (udev->bp.core_enum == USB_CORE_ENUM_HS) { + if (udev->bp.phy_itf == USB_ULPI_PHY) { + udev->regs.dr->DCFG |= USB_SPEED_EXP_HIGH; + } else {/* set High speed PHY in Full speed mode */ + udev->regs.dr->DCFG |= USB_SPEED_EXP_FULL; + } + + /* Set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_HS_SIZE); + + /* Set endpoint 0 to 6's TX FIFO length and RAM address */ + for (i = 0; i < USBHS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBHS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all TX FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire RX FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + if ((ep_num == 1U) && (udev->bp.core_enum == USB_CORE_ENUM_HS)) { + udev->regs.dr->DEP1INTEN |= epinten; + } + else +#endif /* USB_HS_DEDICATED_EP1_ENABLED */ + { + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + } + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + if ((ep_num == 1U) && (udev->bp.core_enum == USB_CORE_ENUM_HS)) { + udev->regs.dr->DEP1INTEN &= ~epinten; + } + else +#endif /* USB_HS_DEDICATED_EP1_ENABLED */ + { + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + } + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the TX FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure USB transaction to start OUT transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + +#ifdef INT_HIGH_BW + if (transc->ep_type == (uint8_t)USB_EPTYPE_INTR) { + eplen |= DIEPLEN_MCNT & (3U << 29U); + } +#endif /* INT_HIGH_BW */ + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..c47abac6c7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c @@ -0,0 +1,476 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected USB host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* initialize host configuration register */ + if (USB_ULPI_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_30_60MHZ); + } else { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic TX FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic TX FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USB_HS_CORE + if (USB_CORE_ENUM_HS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_HS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_HS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_HS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_HS_SIZE + USB_HTX_NPFIFO_HS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_HS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_HS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all TX FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == udev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in FIFO space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the TX fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..04844af1aa --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,587 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); + +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + udev->dev.cur_status = USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + +/*! + \brief USB dedicated OUT endpoint 1 interrupt service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +uint32_t usbd_int_dedicated_ep1out (usb_core_driver *udev) +{ + uint32_t oepintr = 0U; + uint32_t oeplen = 0U; + + oepintr = udev->regs.er_out[1]->DOEPINTF; + oepintr &= udev->regs.dr->DOEP1INTEN; + + /* transfer complete */ + if(oepintr & DOEPINTF_TF){ + /* clear the bit in DOEPINTn for this interrupt */ + udev->regs.er_out[1]->DOEPINTF = DOEPINTF_TF; + + if(USB_USE_DMA == udev->bp.transfer_mode){ + oeplen = udev->regs.er_out[1]->DOEPLEN; + + /* to do : handle more than one single max packet size packet */ + udev->dev.transc_out[1].xfer_count = udev->dev.transc_out[1].max_len - \ + (oeplen & DEPLEN_TLEN); + } + + /* rx complete */ + usbd_out_transc (udev, 1U); + } + + return 1U; +} + +/*! + \brief USB dedicated IN endpoint 1 interrupt service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +uint32_t usbd_int_dedicated_ep1in (usb_core_driver *udev) +{ + uint32_t inten, intr, emptyen; + + inten = udev->regs.dr->DIEP1INTEN; + emptyen = udev->regs.dr->DIEPFEINTEN; + + inten |= ((emptyen >> 1 ) & 0x1) << 7; + + intr = udev->regs.er_in[1]->DIEPINTF & inten; + + if(intr & DIEPINTF_TF){ + udev->regs.dr->DIEPFEINTEN &= ~(0x1 << 1); + + udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TF; + + /* TX complete */ + usbd_in_transc (udev, 1); + } + + if(intr & DIEPINTF_TXFE){ + usbd_emptytxfifo_write(udev, 1); + + udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TXFE; + } + + return 1; +} + +#endif + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + +#ifdef USE_USB_HS + #ifndef USE_450Z_EVAL + /* ensure no-DMA mode can work */ + if ((1U == ep_num) && (0U == (udev->regs.er_out[ep_num]->DOEPLEN & DEPLEN_PCNT))) { + uint32_t devepctl = udev->regs.er_out[ep_num]->DOEPCTL; + + devepctl |= DEPCTL_SNAK; + devepctl &= ~DEPCTL_EPEN; + devepctl &= ~DEPCTL_EPD; + + udev->regs.er_out[ep_num]->DOEPCTL = devepctl; + } + #endif /* USE_450Z_EVAL */ +#endif /* USE_USB_HS */ + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the TX FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + udev->regs.dr->DOEP1INTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; +#endif + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + udev->regs.dr->DIEP1INTEN = DIEPINTEN_TFEN; +#endif + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..2bde1469a0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(udev->host.data); + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(udev->host.data); + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == udev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + udev->host.backup_xfercount[pp_num] = udev->host.pipe[pp_num].xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..610af2e0c5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + void (*machine)(usb_core_driver *udev, usbh_host *uhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..22cf270ac2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void usr_keybrd_init (void); +/* process keyboard data */ +void usr_keybrd_process_data (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..bf4cd44573 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void usr_mouse_init (void); +/* process mouse data */ +void usr_mouse_process_data (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..d950b03315 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,61 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..8718435c63 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..75e89959fe --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,675 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" + +#include +#include + +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *uhost); +static usbh_status usbh_hid_itf_init (usbh_host *uhost); +static usbh_status usbh_hid_class_req (usbh_host *uhost); +static usbh_status usbh_hid_handle (usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief deinitialize the host pipes used for the HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CHECK_CLASS == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check fifo available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(uhost->data, uhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to USB host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to USB host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..aede5b8cca --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user initialization*/ + usr_keybrd_init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(udev, uhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(udev, uhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + usr_keybrd_process_data(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..e92f0ae972 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + usr_mouse_init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if(usbh_hid_mouse_decode(udev, uhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(udev, uhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + usr_mouse_process_data(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..96218c6cca --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: OK) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..da71b743ae --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *uhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction); +/* reset MSC bot request structure */ +usbh_status usbh_msc_bot_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..6f32ddcf86 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for MSC process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..85cd3c65a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..b5129d8e74 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (uhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(uhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to USB host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clear feature command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clear feature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset MSC bot transfer + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to USB host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..afb992b017 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,556 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + uhost->active_class->class_data = (usbh_msc_handler *)malloc(sizeof(usbh_msc_handler)); + + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + memset(msc, 0U, sizeof(usbh_msc_handler)); + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc->ep_in = ep_desc->bEndpointAddress; + msc->ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc->ep_out = ep_desc->bEndpointAddress; + msc->ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc->ep_in = ep_desc->bEndpointAddress; + msc->ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc->ep_out = ep_desc->bEndpointAddress; + msc->ep_size_out = ep_desc->wMaxPacketSize; + } + + msc->state = MSC_INIT; + msc->error = MSC_OK; + msc->req_state = MSC_REQ_IDLE; + msc->pipe_out = usbh_pipe_allocate(uhost->data, msc->ep_out); + msc->pipe_in = usbh_pipe_allocate(uhost->data, msc->ep_in); + + usbh_msc_bot_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc->pipe_out, + USB_EPTYPE_BULK, + msc->ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc->pipe_in, + USB_EPTYPE_BULK, + msc->ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc->pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc->pipe_in, 0U); + } + + return status; +} + +/*! + \brief de-initialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for receiving error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if ((uhost->control.timer - msc->timer) < 10000U) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..f89d7d740a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host_msc; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host_msc, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host_msc, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host_msc, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host_msc, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..e9566af405 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implementing + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..c8e7ca1e7c --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h @@ -0,0 +1,282 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ + +#ifdef USB_LOW_PWR_ENABLE + uint8_t suspend_flag; +#endif /* USB_LOW_PWR_ENABLE*/ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usb_core_driver *udev, usb_core_enum usb_core, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* de-initialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); +#ifdef USB_LOW_PWR_ENABLE +/* handles the USB resume from suspend mode */ +void usb_hwp_resume(usb_core_driver *udev); +#endif /* USB_LOW_PWR_ENABLE */ + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..3112d1a998 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..e89c5fe22f --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..65f4328c55 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..8cb32af254 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c @@ -0,0 +1,653 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *uhost); +static uint8_t usbh_connect (usbh_host *uhost); +static uint8_t usbh_disconnect (usbh_host *uhost); +static uint8_t usbh_port_enabled (usbh_host *uhost); +static uint8_t usbh_port_disabled (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#ifdef USB_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *udev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usb_core_driver *udev, usb_core_enum usb_core, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + udev->host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + udev->host.pipe[i].err_count = 0U; + udev->host.pipe[i].pp_status = PIPE_IDLE; + udev->host.backup_xfercount[i] = 0U; + } + + udev->host.pipe[0].ep.mps = 8U; + + usb_basic_init (&udev->bp, &udev->regs, usb_core); + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&udev->regs); + + usb_core_init (udev->bp, &udev->regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&udev->regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (udev); + + usb_globalint_enable(&udev->regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + udev->host.data = (void *)uhost; + uhost->data = (void *)udev; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to USB host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief de-initialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(udev, uhost->control.pipe_in_num); + usbh_pipe_free(udev, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + /* check for host port events */ + if (((0U == udev->host.connect_status) || (0U == udev->host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (udev->host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (udev); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (udev->host.port_enabled) { + uhost->cur_state = HOST_DEV_ATTACHED; + + uhost->dev_prop.speed = usb_curspeed_get (udev); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(udev, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(udev, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (udev, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (udev, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#ifdef USB_LOW_PWR_ENABLE + uhost->cur_state = HOST_SUSPENDED; +#else + uhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CHECK_CLASS; + } + } else { + uhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (0U == uhost->class_num) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + uhost->suspend_flag = 1; + usb_hwp_suspend(uhost->data); + uhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + + uhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit(uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(udev); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(udev); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[64]; + usbh_status status = USBH_BUSY; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 max packet size */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (udev, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (udev, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (udev, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (udev, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +#ifdef USB_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif /* USB_LOW_PWR_ENABLE */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..7966d8a9ac --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumeration driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to USB host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to USB host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to USB host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to USB host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to USB device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to USB configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to USB interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to USB endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..7d00be8d2a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to USB core instance + \param[in] dev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(dev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HC_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..63d6121350 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c @@ -0,0 +1,370 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* Toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(uhost->data)- uhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..df3e56538d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..220468f42b --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..dddab34227 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..5e836d36da --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..541bfb037b --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..c52931c91e --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/SConscript b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/SConscript similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/SConscript rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/SConscript diff --git a/bsp/gd32/libraries/HAL_Drivers/SConscript b/bsp/gd32/libraries/HAL_Drivers/SConscript deleted file mode 100644 index 1b47236afa..0000000000 --- a/bsp/gd32/libraries/HAL_Drivers/SConscript +++ /dev/null @@ -1,22 +0,0 @@ -Import('RTT_ROOT') -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() - -# add the general drivers. -src = Split(""" -""") - -# add pin drivers. -if GetDepend('RT_USING_PIN'): - src += ['drv_gpio.c'] - -if GetDepend(['RT_USING_SERIAL']): - src += ['drv_usart.c'] - -path = [cwd] - -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) - -Return('group') diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_usart.h b/bsp/gd32/libraries/HAL_Drivers/drv_usart.h deleted file mode 100644 index a07b0bafce..0000000000 --- a/bsp/gd32/libraries/HAL_Drivers/drv_usart.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-08-20 BruceOu first implementation - */ - -#ifndef __USART_H__ -#define __USART_H__ - -#include -#include - -#define UART_ENABLE_IRQ(n) NVIC_EnableIRQ((n)) -#define UART_DISABLE_IRQ(n) NVIC_DisableIRQ((n)) - -int gd32_hw_usart_init(void); - -#endif diff --git a/bsp/gd32/libraries/HAL_Drivers/Kconfig b/bsp/gd32/libraries/gd32_drivers/Kconfig similarity index 100% rename from bsp/gd32/libraries/HAL_Drivers/Kconfig rename to bsp/gd32/libraries/gd32_drivers/Kconfig diff --git a/bsp/gd32/libraries/gd32_drivers/SConscript b/bsp/gd32/libraries/gd32_drivers/SConscript new file mode 100644 index 0000000000..b33b2c5768 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/SConscript @@ -0,0 +1,36 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() + +# add the general drivers. +src = Split(""" +""") + +# add pin drivers. +if GetDepend('RT_USING_PIN'): + src += ['drv_gpio.c'] + +# add usart drivers. +if GetDepend(['RT_USING_SERIAL']): + src += ['drv_usart.c'] + +# add i2c drivers. +if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']): + if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3'): + src += ['drv_soft_i2c.c'] + +# add spi drivers. +if GetDepend('RT_USING_SPI'): + src += ['drv_spi.c'] + +# add spi flash drivers. +if GetDepend('RT_USING_SFUD'): + src += ['drv_spi_flash.c', 'drv_spi.c'] + +path = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) + +Return('group') diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.c b/bsp/gd32/libraries/gd32_drivers/drv_gpio.c similarity index 81% rename from bsp/gd32/libraries/HAL_Drivers/drv_gpio.c rename to bsp/gd32/libraries/gd32_drivers/drv_gpio.c index 3ff4282c82..6eaa7d9f8c 100644 --- a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,6 +10,7 @@ #include #include +#include #ifdef RT_USING_PIN @@ -26,7 +27,7 @@ static const struct pin_index pins[] = GD32_PIN(6, A, 6), GD32_PIN(7, A, 7), GD32_PIN(8, A, 8), - GD32_PIN(9, A, 9), + GD32_PIN(9, A, 9), GD32_PIN(10, A, 10), GD32_PIN(11, A, 11), GD32_PIN(12, A, 12), @@ -138,6 +139,12 @@ struct rt_pin_irq_hdr pin_irq_hdr_tab[] = }; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) + +/** + * @brief get pin + * @param pin + * @retval None + */ const struct pin_index *get_pin(rt_uint8_t pin) { const struct pin_index *index; @@ -154,12 +161,21 @@ const struct pin_index *get_pin(rt_uint8_t pin) } return index; -}; +} -static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) +/** + * @brief set pin mode + * @param dev, pin, mode + * @retval None + */ +static void gd32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) { const struct pin_index *index = RT_NULL; - rt_uint32_t pin_mode = 0, pin_pupd = 0, pin_odpp = 0; + rt_uint32_t pin_mode = 0; + +#if defined SOC_SERIES_GD32F4xx + rt_uint32_t pin_pupd = 0, pin_odpp = 0; +#endif index = get_pin(pin); if (index == RT_NULL) @@ -169,49 +185,82 @@ static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) /* GPIO Periph clock enable */ rcu_periph_clock_enable(index->clk); - pin_mode = GPIO_MODE_OUTPUT; +#if defined SOC_SERIES_GD32F4xx + pin_mode = GPIO_MODE_OUTPUT; +#else + pin_mode = GPIO_MODE_OUT_PP; +#endif switch(mode) { case PIN_MODE_OUTPUT: /* output setting */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_OUTPUT; pin_pupd = GPIO_PUPD_NONE; pin_odpp = GPIO_OTYPE_PP; +#else + pin_mode = GPIO_MODE_OUT_PP; +#endif break; case PIN_MODE_OUTPUT_OD: /* output setting: od. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_OUTPUT; pin_pupd = GPIO_PUPD_NONE; pin_odpp = GPIO_OTYPE_OD; +#else + pin_mode = GPIO_MODE_OUT_OD; +#endif break; case PIN_MODE_INPUT: /* input setting: not pull. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_INPUT; pin_pupd = GPIO_PUPD_PULLUP | GPIO_PUPD_PULLDOWN; +#else + pin_mode = GPIO_MODE_IN_FLOATING; +#endif break; case PIN_MODE_INPUT_PULLUP: /* input setting: pull up. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_INPUT; pin_pupd = GPIO_PUPD_PULLUP; +#else + pin_mode = GPIO_MODE_IPU; +#endif break; case PIN_MODE_INPUT_PULLDOWN: /* input setting: pull down. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_INPUT; pin_pupd = GPIO_PUPD_PULLDOWN; +#else + pin_mode = GPIO_MODE_IPD; +#endif break; default: break; } +#if defined SOC_SERIES_GD32F4xx gpio_mode_set(index->gpio_periph, pin_mode, pin_pupd, index->pin); if(pin_mode == GPIO_MODE_OUTPUT) { gpio_output_options_set(index->gpio_periph, pin_odpp, GPIO_OSPEED_50MHZ, index->pin); } +#else + gpio_init(index->gpio_periph, pin_mode, GPIO_OSPEED_50MHZ, index->pin); +#endif } -static void _pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) +/** + * @brief pin write + * @param dev, pin, valuie + * @retval None + */ +static void gd32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { const struct pin_index *index = RT_NULL; @@ -224,7 +273,12 @@ static void _pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) gpio_bit_write(index->gpio_periph, index->pin, (bit_status)value); } -static int _pin_read(rt_device_t dev, rt_base_t pin) +/** + * @brief pin read + * @param dev, pin + * @retval None + */ +static int gd32_pin_read(rt_device_t dev, rt_base_t pin) { int value = PIN_LOW; const struct pin_index *index = RT_NULL; @@ -239,6 +293,11 @@ static int _pin_read(rt_device_t dev, rt_base_t pin) return value; } +/** + * @brief bit2bitno + * @param bit + * @retval None + */ rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) { rt_uint8_t i; @@ -252,6 +311,11 @@ rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) return -1; } +/** + * @brief pin write + * @param pinbit + * @retval None + */ rt_inline const struct pin_irq_map *get_pin_irq_map(rt_uint32_t pinbit) { rt_int32_t map_index = bit2bitno(pinbit); @@ -260,9 +324,14 @@ rt_inline const struct pin_irq_map *get_pin_irq_map(rt_uint32_t pinbit) return RT_NULL; } return &pin_irq_map[map_index]; -}; +} -static rt_err_t _pin_attach_irq(struct rt_device *device, rt_int32_t pin, +/** + * @brief pin irq attach + * @param device, pin, mode + * @retval None + */ +static rt_err_t gd32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) { const struct pin_index *index = RT_NULL; @@ -304,7 +373,12 @@ static rt_err_t _pin_attach_irq(struct rt_device *device, rt_int32_t pin, return RT_EOK; } -static rt_err_t _pin_detach_irq(struct rt_device *device, rt_int32_t pin) +/** + * @brief pin irq detach + * @param device, pin + * @retval None + */ +static rt_err_t gd32_pin_detach_irq(struct rt_device *device, rt_int32_t pin) { const struct pin_index *index = RT_NULL; rt_base_t level; @@ -337,7 +411,12 @@ static rt_err_t _pin_detach_irq(struct rt_device *device, rt_int32_t pin) return RT_EOK; } -static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +/** + * @brief pin irq enable + * @param device, pin, enabled + * @retval None + */ +static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) { const struct pin_index *index; const struct pin_irq_map *irqmap; @@ -384,13 +463,21 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint return -RT_EINVAL; } +#if defined SOC_SERIES_GD32F4xx rcu_periph_clock_enable(RCU_SYSCFG); +#else + rcu_periph_clock_enable(RCU_AF); +#endif /* enable and set interrupt priority */ nvic_irq_enable(irqmap->irqno, 5U, 0U); /* connect EXTI line to GPIO pin */ +#if defined SOC_SERIES_GD32F4xx syscfg_exti_line_config(index->port_src, index->pin_src); +#else + gpio_exti_source_select(index->port_src, index->pin_src); +#endif /* configure EXTI line */ exti_init((exti_line_enum)(index->pin), EXTI_INTERRUPT, trigger_mode); @@ -417,15 +504,20 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint const static struct rt_pin_ops gd32_pin_ops = { - _pin_mode, - _pin_write, - _pin_read, - _pin_attach_irq, - _pin_detach_irq, - _pin_irq_enable, + .pin_mode = gd32_pin_mode, + .pin_write = gd32_pin_write, + .pin_read = gd32_pin_read, + .pin_attach_irq = gd32_pin_attach_irq, + .pin_detach_irq= gd32_pin_detach_irq, + .pin_irq_enable = gd32_pin_irq_enable, RT_NULL, }; +/** + * @brief pin write + * @param irqno + * @retval None + */ rt_inline void pin_irq_hdr(int irqno) { if (pin_irq_hdr_tab[irqno].hdr) @@ -434,6 +526,11 @@ rt_inline void pin_irq_hdr(int irqno) } } +/** + * @brief gd32 exit interrupt + * @param exti_line + * @retval None + */ void GD32_GPIO_EXTI_IRQHandler(rt_int8_t exti_line) { if(RESET != exti_interrupt_flag_get((exti_line_enum)(1 << exti_line))) @@ -509,6 +606,7 @@ int rt_hw_pin_init(void) return result; } + INIT_BOARD_EXPORT(rt_hw_pin_init); #endif diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.h b/bsp/gd32/libraries/gd32_drivers/drv_gpio.h similarity index 54% rename from bsp/gd32/libraries/HAL_Drivers/drv_gpio.h rename to bsp/gd32/libraries/gd32_drivers/drv_gpio.h index 5b6e32d69b..9300191198 100644 --- a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.h +++ b/bsp/gd32/libraries/gd32_drivers/drv_gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,23 +19,34 @@ extern "C" { #endif -#define GPIOA_BASE (GPIO_BASE + 0x00000800UL) -#define GPIOB_BASE (GPIO_BASE + 0x00000C00UL) -#define GPIOC_BASE (GPIO_BASE + 0x00001000UL) -#define GPIOD_BASE (GPIO_BASE + 0x00001400UL) -#define GPIOE_BASE (GPIO_BASE + 0x00001800UL) -#define GPIOF_BASE (GPIO_BASE + 0x00001C00UL) -#define GPIOG_BASE (GPIO_BASE + 0x00002000UL) +#if defined SOC_SERIES_GD32F10x +#include "gd32f10x_gpio.h" +#elif defined SOC_SERIES_GD32F20x +#include "gd32f20x_gpio.h" +#elif defined SOC_SERIES_GD32F30x +#include "gd32f30x_gpio.h" +#elif defined SOC_SERIES_GD32F4xx +#include "gd32f4xx_gpio.h" +#endif -#define __GD32_PORT(port) GPIO##port##_BASE +#define __GD32_PORT(port) GPIO##port +#if defined SOC_SERIES_GD32F4xx #define GD32_PIN(index, port, pin) {index, RCU_GPIO##port, \ GPIO##port, GPIO_PIN_##pin, \ EXTI_SOURCE_GPIO##port, \ EXTI_SOURCE_PIN##pin} +#else +#define GD32_PIN(index, port, pin) {index, RCU_GPIO##port, \ + GPIO##port, GPIO_PIN_##pin, \ + GPIO_PORT_SOURCE_GPIO##port, \ + GPIO_PIN_SOURCE_##pin} + +#endif + #define GD32_PIN_DEFAULT {-1, (rcu_periph_enum)0, 0, 0, 0, 0} -#define GET_PIN(PORTx, PIN) (rt_base_t)((16 * ( ((rt_base_t)__GD32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) +#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__GD32_PORT(PORTx) - (rt_base_t)GPIO_BASE)/(0x0400UL) )) + PIN) struct pin_index { diff --git a/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c new file mode 100644 index 0000000000..3979d7a36c --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu the first version + */ +#include "drv_soft_i2c.h" + +#ifdef RT_USING_I2C + +#define LOG_TAG "drv.i2c" +#include + +#if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) +#error "Please define at least one BSP_USING_I2Cx" +/* this driver can be disabled at menuconfig → RT-Thread Components → Device Drivers */ +#endif + +static const struct gd32_soft_i2c_config soft_i2c_config[] = +{ +#ifdef BSP_USING_I2C0 + I2C0_BUS_CONFIG, +#endif +#ifdef BSP_USING_I2C1 + I2C1_BUS_CONFIG, +#endif +#ifdef BSP_USING_I2C2 + I2C2_BUS_CONFIG, +#endif +#ifdef BSP_USING_I2C3 + I2C3_BUS_CONFIG, +#endif +}; + +static struct gd32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])]; + +/** + * @brief This function initializes the i2c pin. + * @param i2c + * @retval None + */ +static void gd32_i2c_gpio_init(struct gd32_i2c *i2c) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)i2c->ops.data; + + 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); +} + +/** + * @brief This function sets the sda pin. + * @param data, state + * @retval None + */ +static void gd32_set_sda(void *data, rt_int32_t state) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + if (state) + { + rt_pin_write(cfg->sda, PIN_HIGH); + } + else + { + rt_pin_write(cfg->sda, PIN_LOW); + } +} + +/** + * @brief This function sets the scl pin. + * @param data, state + * @retval None + */ +static void gd32_set_scl(void *data, rt_int32_t state) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + if (state) + { + rt_pin_write(cfg->scl, PIN_HIGH); + } + else + { + rt_pin_write(cfg->scl, PIN_LOW); + } +} + +/** + * @brief This function gets the sda pin state. + * @param data + * @retval None + */ +static rt_int32_t gd32_get_sda(void *data) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + return rt_pin_read(cfg->sda); +} + + +/** + * @brief This function gets the scl pin state. + * @param data + * @retval None + */ +static rt_int32_t gd32_get_scl(void *data) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + return rt_pin_read(cfg->scl); +} + +/** + * @brief The time delay function. + * @param us + * @retval None + */ +static void gd32_udelay(rt_uint32_t us) +{ + int i = ( rcu_clock_freq_get(CK_SYS) / 4000000 * us); + while(i) + { + i--; + } +} + +static const struct rt_i2c_bit_ops gd32_bit_ops_default = +{ + .data = RT_NULL, + .set_sda = gd32_set_sda, + .set_scl = gd32_set_scl, + .get_sda = gd32_get_sda, + .get_scl = gd32_get_scl, + .udelay = gd32_udelay, + .delay_us = 1, + .timeout = 100 +}; + +/** + * @brief if i2c is locked, this function will unlock it + * @param cfg + * @retval RT_EOK indicates successful unlock. + */ +static rt_err_t gd32_i2c_bus_unlock(const struct gd32_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); + gd32_udelay(100); + rt_pin_write(cfg->scl, PIN_LOW); + gd32_udelay(100); + } + } + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +/** + * @brief I2C initialization function + * @param None + * @retval RT_EOK indicates successful initialization. + */ +int rt_hw_i2c_init(void) +{ + rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct gd32_i2c); + rt_err_t result; + + for (int i = 0; i < obj_num; i++) + { + i2c_obj[i].ops = gd32_bit_ops_default; + i2c_obj[i].ops.data = (void*)&soft_i2c_config[i]; + i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops; + gd32_i2c_gpio_init(&i2c_obj[i]); + + result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name); + + RT_ASSERT(result == RT_EOK); + + gd32_i2c_bus_unlock(&soft_i2c_config[i]); + + LOG_D("software simulation %s init done, pin scl: %d, pin sda %d", + soft_i2c_config[i].bus_name, + soft_i2c_config[i].scl, + soft_i2c_config[i].sda); + } + + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_i2c_init); + +#endif /* RT_USING_I2C */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h new file mode 100644 index 0000000000..f7e8b32abf --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu the first version + */ + +#ifndef __DRV_I2C__ +#define __DRV_I2C__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* gd32 config class */ +struct gd32_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; + +/* gd32 i2c dirver class */ +struct gd32_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device i2c2_bus; +}; + +#ifdef BSP_USING_I2C0 +#define I2C4_BUS_CONFIG \ + { \ + .scl = BSP_I2C0_SCL_PIN, \ + .sda = BSP_I2C0_SDA_PIN, \ + .bus_name = "i2c0", \ + } +#endif + +#ifdef BSP_USING_I2C1 +#define I2C1_BUS_CONFIG \ + { \ + .scl = BSP_I2C1_SCL_PIN, \ + .sda = BSP_I2C1_SDA_PIN, \ + .bus_name = "i2c1", \ + } +#endif + +#ifdef BSP_USING_I2C2 +#define I2C2_BUS_CONFIG \ + { \ + .scl = BSP_I2C2_SCL_PIN, \ + .sda = BSP_I2C2_SDA_PIN, \ + .bus_name = "i2c2", \ + } +#endif + +#ifdef BSP_USING_I2C3 +#define I2C3_BUS_CONFIG \ + { \ + .scl = BSP_I2C3_SCL_PIN, \ + .sda = BSP_I2C3_SDA_PIN, \ + .bus_name = "i2c3", \ + } +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_I2C__ */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_spi.c b/bsp/gd32/libraries/gd32_drivers/drv_spi.c new file mode 100644 index 0000000000..023ae2c928 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_spi.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu first implementation + */ +#include "drv_spi.h" + +#ifdef RT_USING_SPI + +#if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) +#define LOG_TAG "drv.spi" + +#include + +#ifdef BSP_USING_SPI0 +static struct rt_spi_bus spi_bus0; +#endif +#ifdef BSP_USING_SPI1 +static struct rt_spi_bus spi_bus1; +#endif +#ifdef BSP_USING_SPI2 +static struct rt_spi_bus spi_bus2; +#endif + +static const struct gd32_spi spi_bus_obj[] = { + +#ifdef BSP_USING_SPI0 + { + SPI0, + "spi0", + RCU_SPI0, + RCU_GPIOA, + &spi_bus0, + GPIOA, + GPIO_PIN_5, + GPIO_PIN_6, + GPIO_PIN_7, + } +#endif /* BSP_USING_SPI0 */ + +#ifdef BSP_USING_SPI1 + { + SPI1, + "spi1", + RCU_SPI1, + RCU_GPIOB, + &spi_bus1, + GPIOB, + GPIO_PIN_12, + GPIO_PIN_14, + GPIO_PIN_15, + } +#endif /* BSP_USING_SPI1 */ + +#ifdef BSP_USING_SPI2 + { + SPI2, + "spi2", + RCU_SPI2, + RCU_GPIOB, + &spi_bus2, + GPIOB, + GPIO_PIN_3, + GPIO_PIN_4, + GPIO_PIN_5, + } +#endif /* BSP_USING_SPI2 */ +}; + +/* private rt-thread spi ops function */ +static rt_err_t spi_configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration); +static rt_uint32_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message); + +static struct rt_spi_ops gd32_spi_ops = +{ + .configure = spi_configure, + .xfer = spixfer, +}; + +/** +* @brief SPI Initialization +* @param gd32_spi: SPI BUS +* @retval None +*/ +static void gd32_spi_init(struct gd32_spi *gd32_spi) +{ + /* enable SPI clock */ + rcu_periph_clock_enable(gd32_spi->spi_clk); + rcu_periph_clock_enable(gd32_spi->gpio_clk); + +#if defined SOC_SERIES_GD32F4xx + /*GPIO pin configuration*/ + gpio_af_set(gd32_spi->spi_port, GPIO_AF_5, gd32_spi->sck_pin | gd32_spi->mosi_pin | gd32_spi->miso_pin); + + gpio_mode_set(gd32_spi->spi_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gd32_spi->miso_pin| gd32_spi->miso_pin); + gpio_output_options_set(gd32_spi->spi_port, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,gd32_spi->miso_pin| gd32_spi->miso_pin); + +#else + /* Init SPI SCK MOSI */ + gpio_init(gd32_spi->spi_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, gd32_spi->sck_pin | gd32_spi->mosi_pin); + + /* Init SPI MISO */ + gpio_init(gd32_spi->spi_port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, gd32_spi->miso_pin); +#endif + +} + +static rt_err_t spi_configure(struct rt_spi_device* device, + struct rt_spi_configuration* configuration) +{ + struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus; + struct gd32_spi *spi_device = (struct gd32_spi *)spi_bus->parent.user_data; + spi_parameter_struct spi_init_struct; + uint32_t spi_periph = spi_device->spi_periph; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + //Init SPI + gd32_spi_init(spi_device); + + /* data_width */ + if(configuration->data_width <= 8) + { + spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; + } + else if(configuration->data_width <= 16) + { + spi_init_struct.frame_size = SPI_FRAMESIZE_16BIT; + } + else + { + return RT_EIO; + } + + /* baudrate */ + { + rcu_clock_freq_enum spi_src; + uint32_t spi_apb_clock; + uint32_t max_hz; + + max_hz = configuration->max_hz; + + LOG_D("sys freq: %d\n", rcu_clock_freq_get(CK_SYS)); + LOG_D("CK_APB2 freq: %d\n", rcu_clock_freq_get(CK_APB2)); + LOG_D("max freq: %d\n", max_hz); + + if (spi_periph == SPI1 || spi_periph == SPI2) + { + spi_src = CK_APB1; + } + else + { + spi_src = CK_APB2; + } + spi_apb_clock = rcu_clock_freq_get(spi_src); + + if(max_hz >= spi_apb_clock/2) + { + spi_init_struct.prescale = SPI_PSC_2; + } + else if (max_hz >= spi_apb_clock/4) + { + spi_init_struct.prescale = SPI_PSC_4; + } + else if (max_hz >= spi_apb_clock/8) + { + spi_init_struct.prescale = SPI_PSC_8; + } + else if (max_hz >= spi_apb_clock/16) + { + spi_init_struct.prescale = SPI_PSC_16; + } + else if (max_hz >= spi_apb_clock/32) + { + spi_init_struct.prescale = SPI_PSC_32; + } + else if (max_hz >= spi_apb_clock/64) + { + spi_init_struct.prescale = SPI_PSC_64; + } + else if (max_hz >= spi_apb_clock/128) + { + spi_init_struct.prescale = SPI_PSC_128; + } + else + { + /* min prescaler 256 */ + spi_init_struct.prescale = SPI_PSC_256; + } + } /* baudrate */ + + switch(configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + break; + case RT_SPI_MODE_1: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; + break; + case RT_SPI_MODE_2: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE; + break; + case RT_SPI_MODE_3: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; + break; + } + + /* MSB or LSB */ + if(configuration->mode & RT_SPI_MSB) + { + spi_init_struct.endian = SPI_ENDIAN_MSB; + } + else + { + spi_init_struct.endian = SPI_ENDIAN_LSB; + } + + spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_init_struct.device_mode = SPI_MASTER; + spi_init_struct.nss = SPI_NSS_SOFT; + + spi_crc_off(spi_periph); + + /* init SPI */ + spi_init(spi_periph, &spi_init_struct); + /* Enable SPI_MASTER */ + spi_enable(spi_periph); + + return RT_EOK; +}; + +static rt_uint32_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message) +{ + struct rt_spi_bus * gd32_spi_bus = (struct rt_spi_bus *)device->bus; + struct gd32_spi *spi_device = (struct gd32_spi *)gd32_spi_bus->parent.user_data; + struct rt_spi_configuration * config = &device->config; + struct gd32_spi_cs * gd32_spi_cs = device->parent.user_data; + uint32_t spi_periph = spi_device->spi_periph; + + RT_ASSERT(device != NULL); + RT_ASSERT(message != NULL); + + /* take CS */ + if(message->cs_take) + { + gpio_bit_reset(gd32_spi_cs->GPIOx, gd32_spi_cs->GPIO_Pin); + LOG_D("spi take cs\n"); + } + + { + if(config->data_width <= 8) + { + const rt_uint8_t * send_ptr = message->send_buf; + rt_uint8_t * recv_ptr = message->recv_buf; + rt_uint32_t size = message->length; + + LOG_D("spi poll transfer start: %d\n", size); + + while(size--) + { + rt_uint8_t data = 0xFF; + + if(send_ptr != RT_NULL) + { + data = *send_ptr++; + } + + // Todo: replace register read/write by gd32f4 lib + //Wait until the transmit buffer is empty + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); + // Send the byte + spi_i2s_data_transmit(spi_periph, data); + + //Wait until a data is received + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); + // Get the received data + data = spi_i2s_data_receive(spi_periph); + + if(recv_ptr != RT_NULL) + { + *recv_ptr++ = data; + } + } + LOG_D("spi poll transfer finsh\n"); + } + else if(config->data_width <= 16) + { + const rt_uint16_t * send_ptr = message->send_buf; + rt_uint16_t * recv_ptr = message->recv_buf; + rt_uint32_t size = message->length; + + while(size--) + { + rt_uint16_t data = 0xFF; + + if(send_ptr != RT_NULL) + { + data = *send_ptr++; + } + + //Wait until the transmit buffer is empty + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); + // Send the byte + spi_i2s_data_transmit(spi_periph, data); + + //Wait until a data is received + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); + // Get the received data + data = spi_i2s_data_receive(spi_periph); + + if(recv_ptr != RT_NULL) + { + *recv_ptr++ = data; + } + } + } + } + + /* release CS */ + if(message->cs_release) + { + gpio_bit_set(gd32_spi_cs->GPIOx, gd32_spi_cs->GPIO_Pin); + LOG_D("spi release cs\n"); + } + + return message->length; +}; + +int rt_hw_spi_init(void) +{ + int result = 0; + int i; + + for (i = 0; i < sizeof(spi_bus_obj) / sizeof(spi_bus_obj[0]); i++) + { + spi_bus_obj[i].spi_bus->parent.user_data = (void *)&spi_bus_obj[i]; + + result = rt_spi_bus_register(spi_bus_obj[i].spi_bus, spi_bus_obj[i].bus_name, &gd32_spi_ops); + + RT_ASSERT(result == RT_EOK); + + LOG_D("%s bus init done", spi_bus_obj[i].bus_name); + } + + return result; +} + +INIT_BOARD_EXPORT(rt_hw_spi_init); + +#endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */ +#endif /* RT_USING_SPI */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_spi.h b/bsp/gd32/libraries/gd32_drivers/drv_spi.h new file mode 100644 index 0000000000..6359d75bd1 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_spi.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu first implementation + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct gd32_spi_cs +{ + uint32_t GPIOx; + uint32_t GPIO_Pin; +}; + +/* gd32 spi dirver class */ +struct gd32_spi +{ + uint32_t spi_periph; + char *bus_name; + rcu_periph_enum spi_clk; + rcu_periph_enum gpio_clk; + struct rt_spi_bus *spi_bus; + uint32_t spi_port; + uint16_t sck_pin; + uint16_t miso_pin; + uint16_t mosi_pin; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_SPI_H__ */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c b/bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c new file mode 100644 index 0000000000..ea2750d7cd --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-31 BruceOu first implementation + */ +#include +#include "drv_spi.h" +#include "spi_flash.h" + +#ifdef RT_USING_SFUD +#include "spi_flash_sfud.h" +#endif + +#include +#include + +#define SPI_BUS_NAME "spi0" +#define SPI_DEVICE_NAME "spi01" +#define SPI_FLASH_DEVICE_NAME "gd25q" + +#define GD25Q_SPI_CS_GPIOX GPIOE +#define GD25Q_SPI_CS_GPIOX_PIN_X GPIO_PIN_3 + +static int rt_hw_spi_flash_init(void) +{ + rt_err_t res; + static struct rt_spi_device spi_dev_gd25q; /* SPI device */ + static struct gd32_spi_cs spi_cs; + spi_cs.GPIOx = GD25Q_SPI_CS_GPIOX; + spi_cs.GPIO_Pin = GD25Q_SPI_CS_GPIOX_PIN_X; + +#if defined SOC_SERIES_GD32F4xx + gpio_mode_set(spi_cs.GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, spi_cs.GPIO_Pin); + gpio_output_options_set(spi_cs.GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, spi_cs.GPIO_Pin); + + gpio_bit_set(spi_cs.GPIOx, spi_cs.GPIO_Pin); +#else + gpio_init(spi_cs.GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, spi_cs.GPIO_Pin); + +#endif + res = rt_spi_bus_attach_device(&spi_dev_gd25q, SPI_FLASH_DEVICE_NAME, SPI_BUS_NAME, (void*)&spi_cs); + + if (res != RT_EOK) + { + rt_kprintf("rt_spi_bus_attach_device() run failed!\n"); + return res; + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spi_flash_init); + +#ifdef RT_USING_SFUD +static int rt_hw_spi_flash_with_sfud_init(void) +{ + if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME)) + { + return RT_ERROR; + }; + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init) +#endif + +#ifdef RT_USING_DFS +#include + +int mnt_init(void) +{ + if (dfs_mount(SPI_FLASH_DEVICE_NAME, "/", "elm", 0, 0) == 0) + { + rt_kprintf("spi flash mount success !\n"); + } + else + { + rt_kprintf("spi flash mount failed!\n"); + } + + return 0; +} +MSH_CMD_EXPORT(mnt_init, mount spi flash to file system); +#endif diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_usart.c b/bsp/gd32/libraries/gd32_drivers/drv_usart.c similarity index 77% rename from bsp/gd32/libraries/HAL_Drivers/drv_usart.c rename to bsp/gd32/libraries/gd32_drivers/drv_usart.c index 54a36d6f73..7671b6da4f 100644 --- a/bsp/gd32/libraries/HAL_Drivers/drv_usart.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_usart.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,8 +7,8 @@ * Date Author Notes * 2021-08-20 BruceOu first implementation */ + #include "drv_usart.h" -#include #ifdef RT_USING_SERIAL @@ -22,27 +22,7 @@ #include -/* GD32 uart driver */ -// Todo: compress uart info -struct gd32_uart -{ - uint32_t uart_periph; //Todo: 3bits - IRQn_Type irqn; //Todo: 7bits - rcu_periph_enum per_clk; //Todo: 5bits - rcu_periph_enum tx_gpio_clk; //Todo: 5bits - rcu_periph_enum rx_gpio_clk; //Todo: 5bits - uint32_t tx_port; //Todo: 4bits - uint16_t tx_af; //Todo: 4bits - uint16_t tx_pin; //Todo: 4bits - uint32_t rx_port; //Todo: 4bits - uint16_t rx_af; //Todo: 4bits - uint16_t rx_pin; //Todo: 4bits - - struct rt_serial_device * serial; - char *device_name; -}; - -static void uart_isr(struct rt_serial_device *serial); +static void GD32_UART_IRQHandler(struct rt_serial_device *serial); #if defined(BSP_USING_UART0) struct rt_serial_device serial0; @@ -52,7 +32,7 @@ void USART0_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial0); + GD32_UART_IRQHandler(&serial0); /* leave interrupt */ rt_interrupt_leave(); @@ -68,7 +48,7 @@ void USART1_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial1); + GD32_UART_IRQHandler(&serial1); /* leave interrupt */ rt_interrupt_leave(); @@ -84,7 +64,7 @@ void USART2_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial2); + GD32_UART_IRQHandler(&serial2); /* leave interrupt */ rt_interrupt_leave(); @@ -100,7 +80,7 @@ void UART3_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial3); + GD32_UART_IRQHandler(&serial3); /* leave interrupt */ rt_interrupt_leave(); @@ -116,7 +96,7 @@ void UART4_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial4); + GD32_UART_IRQHandler(&serial4); /* leave interrupt */ rt_interrupt_leave(); @@ -131,7 +111,7 @@ void USART5_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial5); + GD32_UART_IRQHandler(&serial5); /* leave interrupt */ rt_interrupt_leave(); @@ -147,7 +127,7 @@ void UART6_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial6); + GD32_UART_IRQHandler(&serial6); /* leave interrupt */ rt_interrupt_leave(); @@ -163,7 +143,7 @@ void UART7_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial7); + GD32_UART_IRQHandler(&serial7); /* leave interrupt */ rt_interrupt_leave(); @@ -171,14 +151,19 @@ void UART7_IRQHandler(void) #endif /* BSP_USING_UART7 */ -static const struct gd32_uart uarts[] = { +static const struct gd32_uart uart_obj[] = { #ifdef BSP_USING_UART0 { USART0, // uart peripheral index USART0_IRQn, // uart iqrn RCU_USART0, RCU_GPIOA, RCU_GPIOA, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOA, GPIO_AF_7, GPIO_PIN_9, // tx port, tx alternate, tx pin GPIOA, GPIO_AF_7, GPIO_PIN_10, // rx port, rx alternate, rx pin +#else + GPIOA, GPIO_PIN_9, // tx port, tx pin + GPIOA, GPIO_PIN_10, // rx port, rx pin +#endif &serial0, "uart0", }, @@ -189,8 +174,13 @@ static const struct gd32_uart uarts[] = { USART1, // uart peripheral index USART1_IRQn, // uart iqrn RCU_USART1, RCU_GPIOA, RCU_GPIOA, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOA, GPIO_AF_7, GPIO_PIN_2, // tx port, tx alternate, tx pin GPIOA, GPIO_AF_7, GPIO_PIN_3, // rx port, rx alternate, rx pin +#else + GPIOA, GPIO_PIN_2, // tx port, tx pin + GPIOA, GPIO_PIN_3, // rx port, rx pin +#endif &serial1, "uart1", }, @@ -201,8 +191,13 @@ static const struct gd32_uart uarts[] = { USART2, // uart peripheral index USART2_IRQn, // uart iqrn RCU_USART2, RCU_GPIOB, RCU_GPIOB, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOB, GPIO_AF_7, GPIO_PIN_10, // tx port, tx alternate, tx pin GPIOB, GPIO_AF_7, GPIO_PIN_11, // rx port, rx alternate, rx pin +#else + GPIOB, GPIO_PIN_10, // tx port, tx pin + GPIOB, GPIO_PIN_11, // rx port, rx pin +#endif &serial2, "uart2", }, @@ -213,8 +208,13 @@ static const struct gd32_uart uarts[] = { UART3, // uart peripheral index UART3_IRQn, // uart iqrn RCU_UART3, RCU_GPIOC, RCU_GPIOC, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOC, GPIO_AF_8, GPIO_PIN_10, // tx port, tx alternate, tx pin GPIOC, GPIO_AF_8, GPIO_PIN_11, // rx port, rx alternate, rx pin +#else + GPIOC, GPIO_PIN_10, // tx port, tx pin + GPIOC, GPIO_PIN_11, // rx port, rx pin +#endif &serial3, "uart3", }, @@ -225,8 +225,13 @@ static const struct gd32_uart uarts[] = { UART4, // uart peripheral index UART4_IRQn, // uart iqrn RCU_UART4, RCU_GPIOC, RCU_GPIOD, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOC, GPIO_AF_8, GPIO_PIN_12, // tx port, tx alternate, tx pin GPIOD, GPIO_AF_8, GPIO_PIN_2, // rx port, rx alternate, rx pin +#else + GPIOC, GPIO_PIN_12, // tx port, tx pin + GPIOD, GPIO_PIN_2, // rx port, rx pin +#endif &serial4, "uart4", }, @@ -237,8 +242,13 @@ static const struct gd32_uart uarts[] = { USART5, // uart peripheral index USART5_IRQn, // uart iqrn RCU_USART5, RCU_GPIOC, RCU_GPIOC, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOC, GPIO_AF_8, GPIO_PIN_6, // tx port, tx alternate, tx pin GPIOC, GPIO_AF_8, GPIO_PIN_7, // rx port, rx alternate, rx pin +#else + GPIOC, GPIO_PIN_6, // tx port, tx pin + GPIOC, GPIO_PIN_7, // rx port, rx pin +#endif &serial5, "uart5", }, @@ -249,8 +259,13 @@ static const struct gd32_uart uarts[] = { UART6, // uart peripheral index UART6_IRQn, // uart iqrn RCU_UART6, RCU_GPIOE, RCU_GPIOE, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOE, GPIO_AF_8, GPIO_PIN_7, // tx port, tx alternate, tx pin GPIOE, GPIO_AF_8, GPIO_PIN_8, // rx port, rx alternate, rx pin +#else + GPIOE, GPIO_PIN_7, // tx port, tx pin + GPIOE, GPIO_PIN_8, // rx port, rx pin +#endif &serial6, "uart6", }, @@ -261,8 +276,13 @@ static const struct gd32_uart uarts[] = { UART7, // uart peripheral index UART7_IRQn, // uart iqrn RCU_UART7, RCU_GPIOE, RCU_GPIOE, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOE, GPIO_AF_8, GPIO_PIN_0, // tx port, tx alternate, tx pin GPIOE, GPIO_AF_8, GPIO_PIN_1, // rx port, rx alternate, rx pin +#else + GPIOE, GPIO_PIN_0, // tx port, tx pin + GPIOE, GPIO_PIN_1, // rx port, rx pin +#endif &serial7, "uart7", }, @@ -286,6 +306,7 @@ void gd32_uart_gpio_init(struct gd32_uart *uart) rcu_periph_clock_enable(uart->rx_gpio_clk); rcu_periph_clock_enable(uart->per_clk); +#if defined SOC_SERIES_GD32F4xx /* connect port to USARTx_Tx */ gpio_af_set(uart->tx_port, uart->tx_af, uart->tx_pin); @@ -300,11 +321,24 @@ void gd32_uart_gpio_init(struct gd32_uart *uart) gpio_mode_set(uart->rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, uart->rx_pin); gpio_output_options_set(uart->rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uart->rx_pin); +#else + /* connect port to USARTx_Tx */ + gpio_init(uart->tx_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, uart->tx_pin); + + /* connect port to USARTx_Rx */ + gpio_init(uart->rx_port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, uart->rx_pin); +#endif + NVIC_SetPriority(uart->irqn, 0); NVIC_EnableIRQ(uart->irqn); } -static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +/** + * @brief uart configure + * @param serial, cfg + * @retval None + */ +static rt_err_t gd32_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { struct gd32_uart *uart; @@ -358,7 +392,12 @@ static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_c return RT_EOK; } -static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg) +/** + * @brief uart control + * @param serial, arg + * @retval None + */ +static rt_err_t gd32_uart_control(struct rt_serial_device *serial, int cmd, void *arg) { struct gd32_uart *uart; @@ -385,7 +424,12 @@ static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *ar return RT_EOK; } -static int _uart_putc(struct rt_serial_device *serial, char ch) +/** + * @brief uart put char + * @param serial, ch + * @retval None + */ +static int gd32_uart_putc(struct rt_serial_device *serial, char ch) { struct gd32_uart *uart; @@ -398,7 +442,12 @@ static int _uart_putc(struct rt_serial_device *serial, char ch) return RT_EOK; } -static int _uart_getc(struct rt_serial_device *serial) +/** + * @brief uart get char + * @param serial + * @retval None + */ +static int gd32_uart_getc(struct rt_serial_device *serial) { int ch; struct gd32_uart *uart; @@ -417,7 +466,7 @@ static int _uart_getc(struct rt_serial_device *serial) * * @param serial serial device */ -static void uart_isr(struct rt_serial_device *serial) +static void GD32_UART_IRQHandler(struct rt_serial_device *serial) { struct gd32_uart *uart = (struct gd32_uart *) serial->parent.user_data; @@ -435,12 +484,18 @@ static void uart_isr(struct rt_serial_device *serial) static const struct rt_uart_ops gd32_uart_ops = { - _uart_configure, - _uart_control, - _uart_putc, - _uart_getc, + .configure = gd32_uart_configure, + .control = gd32_uart_control, + .putc = gd32_uart_putc, + .getc = gd32_uart_getc, + RT_NULL, }; +/** + * @brief uart init + * @param None + * @retval None + */ int gd32_hw_usart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; @@ -448,20 +503,22 @@ int gd32_hw_usart_init(void) int result; - for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) + for (i = 0; i < sizeof(uart_obj) / sizeof(uart_obj[0]); i++) { - uarts[i].serial->ops = &gd32_uart_ops; - uarts[i].serial->config = config; + uart_obj[i].serial->ops = &gd32_uart_ops; + uart_obj[i].serial->config = config; /* register UART1 device */ - result = rt_hw_serial_register(uarts[i].serial, - uarts[i].device_name, + result = rt_hw_serial_register(uart_obj[i].serial, + uart_obj[i].device_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, - (void *)&uarts[i]); + (void *)&uart_obj[i]); RT_ASSERT(result == RT_EOK); } return result; } + INIT_BOARD_EXPORT(gd32_hw_usart_init); + #endif diff --git a/bsp/gd32/libraries/gd32_drivers/drv_usart.h b/bsp/gd32/libraries/gd32_drivers/drv_usart.h new file mode 100644 index 0000000000..824cc9c812 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_usart.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#ifndef __DRV_USART_H__ +#define __DRV_USART_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define UART_ENABLE_IRQ(n) NVIC_EnableIRQ((n)) +#define UART_DISABLE_IRQ(n) NVIC_DisableIRQ((n)) + + +/* GD32 uart driver */ +// Todo: compress uart info +struct gd32_uart +{ + uint32_t uart_periph; //Todo: 3bits + IRQn_Type irqn; //Todo: 7bits + rcu_periph_enum per_clk; //Todo: 5bits + rcu_periph_enum tx_gpio_clk; //Todo: 5bits + rcu_periph_enum rx_gpio_clk; //Todo: 5bits + uint32_t tx_port; //Todo: 4bits +#if defined SOC_SERIES_GD32F4xx + uint16_t tx_af; //Todo: 4bits +#endif + uint16_t tx_pin; //Todo: 4bits + uint32_t rx_port; //Todo: 4bits +#if defined SOC_SERIES_GD32F4xx + uint16_t rx_af; //Todo: 4bits +#endif + uint16_t rx_pin; //Todo: 4bits + + struct rt_serial_device * serial; + char *device_name; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_USART_H__ */ diff --git a/bsp/gd32/tools/sdk_dist.py b/bsp/gd32/tools/sdk_dist.py index cc5ccce7c6..d6f97a3835 100644 --- a/bsp/gd32/tools/sdk_dist.py +++ b/bsp/gd32/tools/sdk_dist.py @@ -5,7 +5,20 @@ import shutil cwd_path = os.getcwd() sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools')) +def bsp_update_board_kconfig(dist_dir): + # change board/kconfig path + if not os.path.isfile(os.path.join(dist_dir, 'board/Kconfig')): + return + with open(os.path.join(dist_dir, 'board/Kconfig'), 'r') as f: + data = f.readlines() + with open(os.path.join(dist_dir, 'board/Kconfig'), 'w') as f: + for line in data: + if line.find('../libraries/gd32_drivers/Kconfig') != -1: + position = line.find('../libraries/gd32_drivers/Kconfig') + line = line[0:position] + 'libraries/gd32_drivers/Kconfig"\n' + f.write(line) + # BSP dist function def dist_do_building(BSP_ROOT, dist_dir): from mkdist import bsp_copy_files @@ -18,5 +31,7 @@ def dist_do_building(BSP_ROOT, dist_dir): os.path.join(library_dir, rtconfig.BSP_LIBRARY_TYPE)) print("=> copy bsp drivers") - bsp_copy_files(os.path.join(library_path, 'HAL_Drivers'), os.path.join(library_dir, 'HAL_Drivers')) + bsp_copy_files(os.path.join(library_path, 'gd32_drivers'), os.path.join(library_dir, 'gd32_drivers')) shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + bsp_update_board_kconfig(dist_dir)